You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
152 lines
3.6 KiB
152 lines
3.6 KiB
// Copyright 2012 Gary Burd |
|
// |
|
// Licensed under the Apache License, Version 2.0 (the "License"): you may |
|
// not use this file except in compliance with the License. You may obtain |
|
// a copy of the License at |
|
// |
|
// http://www.apache.org/licenses/LICENSE-2.0 |
|
// |
|
// Unless required by applicable law or agreed to in writing, software |
|
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
|
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
|
// License for the specific language governing permissions and limitations |
|
// under the License. |
|
|
|
package redis |
|
|
|
import ( |
|
"errors" |
|
|
|
pkgerr "github.com/pkg/errors" |
|
) |
|
|
|
var ( |
|
errPubSub = errors.New("redigo: unknown pubsub notification") |
|
) |
|
|
|
// Subscription represents a subscribe or unsubscribe notification. |
|
type Subscription struct { |
|
|
|
// Kind is "subscribe", "unsubscribe", "psubscribe" or "punsubscribe" |
|
Kind string |
|
|
|
// The channel that was changed. |
|
Channel string |
|
|
|
// The current number of subscriptions for connection. |
|
Count int |
|
} |
|
|
|
// Message represents a message notification. |
|
type Message struct { |
|
|
|
// The originating channel. |
|
Channel string |
|
|
|
// The message data. |
|
Data []byte |
|
} |
|
|
|
// PMessage represents a pmessage notification. |
|
type PMessage struct { |
|
|
|
// The matched pattern. |
|
Pattern string |
|
|
|
// The originating channel. |
|
Channel string |
|
|
|
// The message data. |
|
Data []byte |
|
} |
|
|
|
// Pong represents a pubsub pong notification. |
|
type Pong struct { |
|
Data string |
|
} |
|
|
|
// PubSubConn wraps a Conn with convenience methods for subscribers. |
|
type PubSubConn struct { |
|
Conn Conn |
|
} |
|
|
|
// Close closes the connection. |
|
func (c PubSubConn) Close() error { |
|
return c.Conn.Close() |
|
} |
|
|
|
// Subscribe subscribes the connection to the specified channels. |
|
func (c PubSubConn) Subscribe(channel ...interface{}) error { |
|
c.Conn.Send("SUBSCRIBE", channel...) |
|
return c.Conn.Flush() |
|
} |
|
|
|
// PSubscribe subscribes the connection to the given patterns. |
|
func (c PubSubConn) PSubscribe(channel ...interface{}) error { |
|
c.Conn.Send("PSUBSCRIBE", channel...) |
|
return c.Conn.Flush() |
|
} |
|
|
|
// Unsubscribe unsubscribes the connection from the given channels, or from all |
|
// of them if none is given. |
|
func (c PubSubConn) Unsubscribe(channel ...interface{}) error { |
|
c.Conn.Send("UNSUBSCRIBE", channel...) |
|
return c.Conn.Flush() |
|
} |
|
|
|
// PUnsubscribe unsubscribes the connection from the given patterns, or from all |
|
// of them if none is given. |
|
func (c PubSubConn) PUnsubscribe(channel ...interface{}) error { |
|
c.Conn.Send("PUNSUBSCRIBE", channel...) |
|
return c.Conn.Flush() |
|
} |
|
|
|
// Ping sends a PING to the server with the specified data. |
|
func (c PubSubConn) Ping(data string) error { |
|
c.Conn.Send("PING", data) |
|
return c.Conn.Flush() |
|
} |
|
|
|
// Receive returns a pushed message as a Subscription, Message, PMessage, Pong |
|
// or error. The return value is intended to be used directly in a type switch |
|
// as illustrated in the PubSubConn example. |
|
func (c PubSubConn) Receive() interface{} { |
|
reply, err := Values(c.Conn.Receive()) |
|
if err != nil { |
|
return err |
|
} |
|
|
|
var kind string |
|
reply, err = Scan(reply, &kind) |
|
if err != nil { |
|
return err |
|
} |
|
|
|
switch kind { |
|
case "message": |
|
var m Message |
|
if _, err := Scan(reply, &m.Channel, &m.Data); err != nil { |
|
return err |
|
} |
|
return m |
|
case "pmessage": |
|
var pm PMessage |
|
if _, err := Scan(reply, &pm.Pattern, &pm.Channel, &pm.Data); err != nil { |
|
return err |
|
} |
|
return pm |
|
case "subscribe", "psubscribe", "unsubscribe", "punsubscribe": |
|
s := Subscription{Kind: kind} |
|
if _, err := Scan(reply, &s.Channel, &s.Count); err != nil { |
|
return err |
|
} |
|
return s |
|
case "pong": |
|
var p Pong |
|
if _, err := Scan(reply, &p.Data); err != nil { |
|
return err |
|
} |
|
return p |
|
} |
|
return pkgerr.WithStack(errPubSub) |
|
}
|
|
|