github.com/therealbill/libredis@v0.0.0-20161227004305-7d50abda5ccf/client/pubsub.go (about) 1 package client 2 3 import ( 4 "errors" 5 "strconv" 6 "strings" 7 ) 8 9 // Publish posts a message to the given channel. 10 // Integer reply: the number of clients that received the message. 11 func (r *Redis) Publish(channel, message string) (int64, error) { 12 rp, err := r.ExecuteCommand("PUBLISH", channel, message) 13 if err != nil { 14 return 0, err 15 } 16 return rp.IntegerValue() 17 } 18 19 // PubSub doc: http://redis.io/topics/pubsub 20 type PubSub struct { 21 redis *Redis 22 conn *connection 23 24 Patterns map[string]bool 25 Channels map[string]bool 26 } 27 28 // GetName returns the address/name of the sentinel we are connected to 29 func (p *PubSub) GetName() string { 30 return p.redis.GetName() 31 } 32 33 // PubSub new a PubSub from *redis. 34 func (r *Redis) PubSub() (*PubSub, error) { 35 c, err := r.pool.Get() 36 if err != nil { 37 return nil, err 38 } 39 return &PubSub{ 40 redis: r, 41 conn: c, 42 Patterns: make(map[string]bool), 43 Channels: make(map[string]bool), 44 }, nil 45 } 46 47 // Close closes current pubsub command. 48 func (p *PubSub) Close() error { 49 return p.conn.Conn.Close() 50 } 51 52 // Receive returns the reply of pubsub command. 53 // A message is a Multi-bulk reply with three elements. 54 // The first element is the kind of message: 55 // 1) subscribe: means that we successfully subscribed to the channel given as the second element in the reply. 56 // The third argument represents the number of channels we are currently subscribed to. 57 // 2) unsubscribe: means that we successfully unsubscribed from the channel given as second element in the reply. 58 // third argument represents the number of channels we are currently subscribed to. 59 // When the last argument is zero, we are no longer subscribed to any channel, 60 // and the client can issue any kind of Redis command as we are outside the Pub/Sub state. 61 // 3) message: it is a message received as result of a PUBLISH command issued by another client. 62 // The second element is the name of the originating channel, and the third argument is the actual message payload. 63 func (p *PubSub) Receive() ([]string, error) { 64 rp, err := p.conn.RecvReply() 65 if err != nil { 66 return nil, err 67 } 68 command, err := rp.Multi[0].StringValue() 69 if err != nil { 70 return nil, err 71 } 72 switch strings.ToLower(command) { 73 case "psubscribe", "punsubscribe": 74 pattern, err := rp.Multi[1].StringValue() 75 if err != nil { 76 return nil, err 77 } 78 if command == "psubscribe" { 79 p.Patterns[pattern] = true 80 } else { 81 delete(p.Patterns, pattern) 82 } 83 number, err := rp.Multi[2].IntegerValue() 84 if err != nil { 85 return nil, err 86 } 87 return []string{command, pattern, strconv.FormatInt(number, 10)}, nil 88 case "subscribe", "unsubscribe": 89 channel, err := rp.Multi[1].StringValue() 90 if err != nil { 91 return nil, err 92 } 93 if command == "subscribe" { 94 p.Channels[channel] = true 95 } else { 96 delete(p.Channels, channel) 97 } 98 number, err := rp.Multi[2].IntegerValue() 99 if err != nil { 100 return nil, err 101 } 102 return []string{command, channel, strconv.FormatInt(number, 10)}, nil 103 case "pmessage": 104 pattern, err := rp.Multi[1].StringValue() 105 if err != nil { 106 return nil, err 107 } 108 channel, err := rp.Multi[2].StringValue() 109 if err != nil { 110 return nil, err 111 } 112 message, err := rp.Multi[3].StringValue() 113 if err != nil { 114 return nil, err 115 } 116 return []string{command, pattern, channel, message}, nil 117 case "message": 118 channel, err := rp.Multi[1].StringValue() 119 if err != nil { 120 return nil, err 121 } 122 message, err := rp.Multi[2].StringValue() 123 if err != nil { 124 return nil, err 125 } 126 return []string{command, channel, message}, nil 127 } 128 return nil, errors.New("pubsub protocol error") 129 } 130 131 // Subscribe channel [channel ...] 132 func (p *PubSub) Subscribe(channels ...string) error { 133 args := packArgs("SUBSCRIBE", channels) 134 return p.conn.SendCommand(args...) 135 } 136 137 // PSubscribe pattern [pattern ...] 138 func (p *PubSub) PSubscribe(patterns ...string) error { 139 args := packArgs("PSUBSCRIBE", patterns) 140 return p.conn.SendCommand(args...) 141 } 142 143 // UnSubscribe [channel [channel ...]] 144 func (p *PubSub) UnSubscribe(channels ...string) error { 145 args := packArgs("UNSUBSCRIBE", channels) 146 return p.conn.SendCommand(args...) 147 } 148 149 // PUnSubscribe [pattern [pattern ...]] 150 func (p *PubSub) PUnSubscribe(patterns ...string) error { 151 args := packArgs("PUNSUBSCRIBE", patterns) 152 return p.conn.SendCommand(args...) 153 }