149 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			149 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // 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"
 | |
| 	"time"
 | |
| )
 | |
| 
 | |
| // 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 matched pattern, if any
 | |
| 	Pattern 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.
 | |
| //
 | |
| // The connection must be subscribed to at least one channel or pattern when
 | |
| // calling this method.
 | |
| 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, 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{} {
 | |
| 	return c.receiveInternal(c.Conn.Receive())
 | |
| }
 | |
| 
 | |
| // ReceiveWithTimeout is like Receive, but it allows the application to
 | |
| // override the connection's default timeout.
 | |
| func (c PubSubConn) ReceiveWithTimeout(timeout time.Duration) interface{} {
 | |
| 	return c.receiveInternal(ReceiveWithTimeout(c.Conn, timeout))
 | |
| }
 | |
| 
 | |
| func (c PubSubConn) receiveInternal(replyArg interface{}, errArg error) interface{} {
 | |
| 	reply, err := Values(replyArg, errArg)
 | |
| 	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 m Message
 | |
| 		if _, err := Scan(reply, &m.Pattern, &m.Channel, &m.Data); err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 		return m
 | |
| 	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 errors.New("redigo: unknown pubsub notification")
 | |
| }
 |