Skip to content

Commit

Permalink
Clarify thread safety. Fixes redis#166.
Browse files Browse the repository at this point in the history
  • Loading branch information
vmihailenco committed Sep 12, 2015
1 parent 02154c3 commit c809246
Show file tree
Hide file tree
Showing 8 changed files with 33 additions and 16 deletions.
9 changes: 6 additions & 3 deletions cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import (
"time"
)

// ClusterClient is a Redis Cluster client representing a pool of zero
// or more underlying connections. It's safe for concurrent use by
// multiple goroutines.
type ClusterClient struct {
commandable

Expand All @@ -26,7 +29,7 @@ type ClusterClient struct {
reloading uint32
}

// NewClusterClient returns a new Redis Cluster client as described in
// NewClusterClient returns a Redis Cluster client as described in
// http://redis.io/topics/cluster-spec.
func NewClusterClient(opt *ClusterOptions) *ClusterClient {
client := &ClusterClient{
Expand All @@ -43,8 +46,8 @@ func NewClusterClient(opt *ClusterOptions) *ClusterClient {

// Close closes the cluster client, releasing any open resources.
//
// It is rare to Close a Client, as the Client is meant to be
// long-lived and shared between many goroutines.
// It is rare to Close a ClusterClient, as the ClusterClient is meant
// to be long-lived and shared between many goroutines.
func (c *ClusterClient) Close() error {
defer c.clientsMx.Unlock()
c.clientsMx.Lock()
Expand Down
5 changes: 3 additions & 2 deletions cluster_pipeline.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ type ClusterPipeline struct {
}

// Pipeline creates a new pipeline which is able to execute commands
// against multiple shards.
// against multiple shards. It's NOT safe for concurrent use by
// multiple goroutines.
func (c *ClusterClient) Pipeline() *ClusterPipeline {
pipe := &ClusterPipeline{
cluster: c,
Expand Down Expand Up @@ -82,7 +83,7 @@ func (pipe *ClusterPipeline) Exec() (cmds []Cmder, retErr error) {
return cmds, retErr
}

// Close marks the pipeline as closed
// Close closes the pipeline, releasing any open resources.
func (pipe *ClusterPipeline) Close() error {
pipe.Discard()
pipe.closed = true
Expand Down
3 changes: 2 additions & 1 deletion multi.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import (
var errDiscard = errors.New("redis: Discard can be used only inside Exec")

// Multi implements Redis transactions as described in
// http://redis.io/topics/transactions.
// http://redis.io/topics/transactions. It's NOT safe for concurrent
// use by multiple goroutines.
type Multi struct {
commandable

Expand Down
6 changes: 3 additions & 3 deletions pipeline.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
package redis

// Pipeline implements pipelining as described in
// http://redis.io/topics/pipelining.
//
// Pipeline is not thread-safe.
// http://redis.io/topics/pipelining. It's NOT safe for concurrent use
// by multiple goroutines.
type Pipeline struct {
commandable

Expand Down Expand Up @@ -36,6 +35,7 @@ func (pipe *Pipeline) process(cmd Cmder) {
pipe.cmds = append(pipe.cmds, cmd)
}

// Close closes the pipeline, releasing any open resources.
func (pipe *Pipeline) Close() error {
pipe.Discard()
pipe.closed = true
Expand Down
3 changes: 2 additions & 1 deletion pubsub.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ func (c *Client) Publish(channel, message string) *IntCmd {
}

// PubSub implements Pub/Sub commands as described in
// http://redis.io/topics/pubsub.
// http://redis.io/topics/pubsub. It's NOT safe for concurrent use by
// multiple goroutines.
type PubSub struct {
*baseClient

Expand Down
7 changes: 7 additions & 0 deletions redis.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ func (c *baseClient) process(cmd Cmder) {
}

// Close closes the client, releasing any open resources.
//
// It is rare to Close a Client, as the Client is meant to be
// long-lived and shared between many goroutines.
func (c *baseClient) Close() error {
return c.connPool.Close()
}
Expand Down Expand Up @@ -173,6 +176,9 @@ func (opt *Options) getIdleTimeout() time.Duration {

//------------------------------------------------------------------------------

// Client is a Redis client representing a pool of zero or more
// underlying connections. It's safe for concurrent use by multiple
// goroutines.
type Client struct {
*baseClient
commandable
Expand All @@ -186,6 +192,7 @@ func newClient(opt *Options, pool pool) *Client {
}
}

// NewClient returns a client to the Redis Server specified by Options.
func NewClient(opt *Options) *Client {
pool := newConnPool(opt)
return newClient(opt, pool)
Expand Down
11 changes: 7 additions & 4 deletions ring.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,8 @@ func (shard *ringShard) Vote(up bool) bool {
}

// Ring is a Redis client that uses constistent hashing to distribute
// keys across multiple Redis servers (shards).
// keys across multiple Redis servers (shards). It's safe for
// concurrent use by multiple goroutines.
//
// It monitors the state of each shard and removes dead shards from
// the ring. When shard comes online it is added back to the ring. This
Expand Down Expand Up @@ -215,8 +216,8 @@ func (ring *Ring) heartbeat() {

// Close closes the ring client, releasing any open resources.
//
// It is rare to Close a Client, as the Client is meant to be
// long-lived and shared between many goroutines.
// It is rare to Close a Ring, as the Ring is meant to be long-lived
// and shared between many goroutines.
func (ring *Ring) Close() (retErr error) {
defer ring.mx.Unlock()
ring.mx.Lock()
Expand All @@ -238,7 +239,8 @@ func (ring *Ring) Close() (retErr error) {
}

// RingPipeline creates a new pipeline which is able to execute commands
// against multiple shards.
// against multiple shards. It's NOT safe for concurrent use by
// multiple goroutines.
type RingPipeline struct {
commandable

Expand Down Expand Up @@ -342,6 +344,7 @@ func (pipe *RingPipeline) Exec() (cmds []Cmder, retErr error) {
return cmds, retErr
}

// Close closes the pipeline, releasing any open resources.
func (pipe *RingPipeline) Close() error {
pipe.Discard()
pipe.closed = true
Expand Down
5 changes: 3 additions & 2 deletions sentinel.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,9 @@ func (opt *FailoverOptions) options() *Options {
}
}

// NewFailoverClient returns a Redis client with automatic failover
// capabilities using Redis Sentinel.
// NewFailoverClient returns a Redis client that uses Redis Sentinel
// for automatic failover. It's safe for concurrent use by multiple
// goroutines.
func NewFailoverClient(failoverOpt *FailoverOptions) *Client {
opt := failoverOpt.options()
failover := &sentinelFailover{
Expand Down

0 comments on commit c809246

Please sign in to comment.