func TestPushed(t *testing.T) { pc := dialt(t) defer pc.Close() nc, err := net.Dial("tcp", ":6379") if err != nil { t.Fatal(err) } defer nc.Close() nc.SetReadDeadline(time.Now().Add(4 * time.Second)) c := redis.PubSubConn{Conn: redis.NewConn(nc, 0, 0)} c.Subscribe("c1") expectPushed(t, c, "Subscribe(c1)", redis.Subscription{Kind: "subscribe", Channel: "c1", Count: 1}) c.Subscribe("c2") expectPushed(t, c, "Subscribe(c2)", redis.Subscription{Kind: "subscribe", Channel: "c2", Count: 2}) c.PSubscribe("p1") expectPushed(t, c, "PSubscribe(p1)", redis.Subscription{Kind: "psubscribe", Channel: "p1", Count: 3}) c.PSubscribe("p2") expectPushed(t, c, "PSubscribe(p2)", redis.Subscription{Kind: "psubscribe", Channel: "p2", Count: 4}) c.PUnsubscribe() expectPushed(t, c, "Punsubscribe(p1)", redis.Subscription{Kind: "punsubscribe", Channel: "p1", Count: 3}) expectPushed(t, c, "Punsubscribe()", redis.Subscription{Kind: "punsubscribe", Channel: "p2", Count: 2}) pc.Do("PUBLISH", "c1", "hello") expectPushed(t, c, "PUBLISH c1 hello", redis.Message{Channel: "c1", Data: []byte("hello")}) }
func main() { c, err := redis.Dial("tcp", ":6379") if err != nil { panic(err) } defer c.Close() psc := redis.PubSubConn{Conn: c} psc.Subscribe("example") psc.PSubscribe("p*") for { switch n := psc.Receive().(type) { case redis.Message: fmt.Printf("Message: %s %s\n", n.Channel, n.Data) case redis.PMessage: fmt.Printf("PMessage: %s %s %s\n", n.Pattern, n.Channel, n.Data) case redis.Subscription: fmt.Printf("Subscription: %s %s %d\n", n.Kind, n.Channel, n.Count) if n.Count == 0 { return } case error: fmt.Printf("error: %v\n", n) return } } }
func main3() { //INIT OMIT c, err := redis.Dial("tcp", ":6379") if err != nil { panic(err) } defer c.Close() //set c.Do("SET", "message1", "Hello World") //get world, err := redis.String(c.Do("GET", "message1")) if err != nil { fmt.Println("key not found") } fmt.Println(world) //ENDINIT OMIT psc := redis.PubSubConn{c} psc.PSubscribe("bigbluebutton:to-bbb-apps:system") for { switch v := psc.Receive().(type) { case redis.Message: fmt.Printf("%s: message: %s\n", v.Channel, v.Data) case redis.PMessage: fmt.Printf("PMessage: %s %s %s\n", v.Pattern, v.Channel, v.Data) case redis.Subscription: fmt.Printf("%s: %s %d\n", v.Channel, v.Kind, v.Count) case error: fmt.Printf("error: %v\n", v) } } }
// Monitor sentinel func MonitorSentinel() { redisConn := gRedisPool.Get() defer redisConn.Close() psc := redis.PubSubConn{redisConn} psc.PSubscribe("*") runflag := true for runflag { switch v := psc.Receive().(type) { case redis.Message: log.Infof("Type Message>>channel %s, message: %s", v.Channel, v.Data) case redis.Subscription: log.Infof("Type Subscribe>>channel %s, kind %s, count %d", v.Channel, v.Kind, v.Count) gRecoveryChan <- RECOVERY_TYPE_REDIS case error: log.Error("MonitorSentinel ERROR") runflag = false // Should re psubscrebe case redis.PMessage: log.Infof("Type PMessage>>channel %s, pattern %s, data %s", v.Channel, v.Pattern, v.Data) ParsePMessage(v) default: log.Warnf("Unkown Message Type of psubscribe") } } }
func (rpsi *RedisPubSubInput) Run(ir pipeline.InputRunner, h pipeline.PluginHelper) error { var ( dRunner pipeline.DecoderRunner decoder pipeline.Decoder pack *pipeline.PipelinePack e error ok bool ) // Get the InputRunner's chan to receive empty PipelinePacks packSupply := ir.InChan() if rpsi.conf.DecoderName != "" { if dRunner, ok = h.DecoderRunner(rpsi.conf.DecoderName, fmt.Sprintf("%s-%s", ir.Name(), rpsi.conf.DecoderName)); !ok { return fmt.Errorf("Decoder not found: %s", rpsi.conf.DecoderName) } decoder = dRunner.Decoder() } //Connect to the channel psc := redis.PubSubConn{Conn: rpsi.conn} psc.PSubscribe(rpsi.conf.Channel) for { switch n := psc.Receive().(type) { case redis.PMessage: // Grab an empty PipelinePack from the InputRunner pack = <-packSupply pack.Message.SetType("redis_pub_sub") pack.Message.SetLogger(n.Channel) pack.Message.SetPayload(string(n.Data)) pack.Message.SetTimestamp(time.Now().UnixNano()) var packs []*pipeline.PipelinePack if decoder == nil { packs = []*pipeline.PipelinePack{pack} } else { packs, e = decoder.Decode(pack) } if packs != nil { for _, p := range packs { ir.Inject(p) } } else { if e != nil { ir.LogError(fmt.Errorf("Couldn't parse Redis message: %s", n.Data)) } pack.Recycle(nil) } case redis.Subscription: ir.LogMessage(fmt.Sprintf("Subscription: %s %s %d\n", n.Kind, n.Channel, n.Count)) if n.Count == 0 { return errors.New("No channel to subscribe") } case error: fmt.Printf("error: %v\n", n) return n } } return nil }
func SubCommonMsg() error { r := Redix[_SubCommonMsg] RedixMu[_SubCommonMsg].Lock() defer RedixMu[_SubCommonMsg].Unlock() psc := redis.PubSubConn{Conn: r} err := psc.PSubscribe(SubCommonMsgKey) if err != nil { return err } ch := make(chan redis.PMessage, 128) go func() { defer psc.Close() for { data := psc.Receive() switch m := data.(type) { case redis.PMessage: ch <- m case redis.Subscription: if m.Count == 0 { glog.Fatalf("Subscription: %s %s %d, %v\n", m.Kind, m.Channel, m.Count, m) return } case error: glog.Errorf("[modifypwd|redis] sub of error: %v\n", m) return } } }() go HandleCommonMsg(ch) return nil }
// getKeyEventChannel returns a channel that sends events for key changes in // Redis. func (r *RedisRTC) getKeyEventChannel(channelOrPattern string, isPattern bool) (<-chan string, error) { // Listen for changes on the queue continously. psc := redis.PubSubConn{Conn: r.redisPool.Get()} subscribe := func() error { if isPattern { return psc.PSubscribe(channelOrPattern) } else { return psc.Subscribe(channelOrPattern) } } // Subscribe to the key events if err := subscribe(); err != nil { return nil, err } readyCh := make(chan bool) ret := make(chan string) go func() { for { Loop: for { switch v := psc.Receive().(type) { case redis.PMessage: ret <- string(v.Data) case redis.Message: ret <- string(v.Data) case redis.Subscription: if readyCh != nil { readyCh <- true close(readyCh) } case error: glog.Errorf("Error waiting for key events: %s", v) glog.Infof("Reconnecting.") util.Close(psc) break Loop } } readyCh = nil psc = redis.PubSubConn{Conn: r.redisPool.Get()} if err := subscribe(); err != nil { glog.Errorf("Error re-connecting: %s", err) time.Sleep(time.Second) } } }() <-readyCh return ret, nil }
// NewReader creates a new redis channel reader func NewReader(key string) (io.ReadCloser, error) { if !NewRedisRegistrar().IsRegistered(key) { return nil, ErrNotRegistered } psc := redis.PubSubConn{Conn: redisPool.Get()} channel := channel(key) psc.PSubscribe(channel.wildcardID()) rd := &reader{ channel: channel, psc: psc, mutex: &sync.Mutex{}} return rd, nil }
func myRedisSubscriptions() (<-chan RedisMsg, <-chan RedisMsg) { // set up structures and channels to stream events out on scoreUpdates := make(chan RedisMsg) detailUpdates := make(chan RedisMsg) // get a new redis connection from pool. // since this is the first time the app tries to do something with redis, // die if we can't get a valid connection, since something is probably // configured wrong. conn := redisPool.Get() _, err := conn.Do("PING") if err != nil { log.Fatal("Could not connect to Redis, check your configuration.") } // subscribe to and handle streams psc := redis.PubSubConn{conn} psc.Subscribe("stream.score_updates") psc.PSubscribe("stream.tweet_updates.*") go func() { for { switch v := psc.Receive().(type) { case redis.Message: //fmt.Printf("%s: message: %s\n", v.Channel, v.Data) scoreUpdates <- RedisMsg{v.Channel, v.Data} //string(v.Data) case redis.PMessage: //fmt.Printf("pattern: %s, channel: %s, data: %s\n", v.Pattern, v.Channel, v.Data) //TODO: at some point we might need to also match the pattern here for kiosk mode detailUpdates <- RedisMsg{v.Channel, v.Data} case error: log.Println("redis subscribe connection errored?@&*(#)akjd") // probable cause is connection was closed, but force close just in case conn.Close() log.Println("attempting to get a new one in 5 seconds...") time.Sleep(5 * time.Second) conn = redisPool.Get() } } }() return scoreUpdates, detailUpdates }
func TestPushed(t *testing.T) { pc, err := redis.DialDefaultServer() if err != nil { t.Fatalf("error connection to database, %v", err) } defer pc.Close() sc, err := redis.DialDefaultServer() if err != nil { t.Fatalf("error connection to database, %v", err) } defer sc.Close() c := redis.PubSubConn{Conn: sc} c.Subscribe("c1") expectPushed(t, c, "Subscribe(c1)", redis.Subscription{Kind: "subscribe", Channel: "c1", Count: 1}) c.Subscribe("c2") expectPushed(t, c, "Subscribe(c2)", redis.Subscription{Kind: "subscribe", Channel: "c2", Count: 2}) c.PSubscribe("p1") expectPushed(t, c, "PSubscribe(p1)", redis.Subscription{Kind: "psubscribe", Channel: "p1", Count: 3}) c.PSubscribe("p2") expectPushed(t, c, "PSubscribe(p2)", redis.Subscription{Kind: "psubscribe", Channel: "p2", Count: 4}) c.PUnsubscribe() expectPushed(t, c, "Punsubscribe(p1)", redis.Subscription{Kind: "punsubscribe", Channel: "p1", Count: 3}) expectPushed(t, c, "Punsubscribe()", redis.Subscription{Kind: "punsubscribe", Channel: "p2", Count: 2}) pc.Do("PUBLISH", "c1", "hello") expectPushed(t, c, "PUBLISH c1 hello", redis.Message{Channel: "c1", Data: []byte("hello")}) c.Ping("hello") expectPushed(t, c, `Ping("hello")`, redis.Pong{Data: "hello"}) c.Conn.Send("PING") c.Conn.Flush() expectPushed(t, c, `Send("PING")`, redis.Pong{}) }
// Applications can receive pushed messages from one goroutine and manage subscriptions from another goroutine. func ExamplePubSubConn() { c, err := dial() if err != nil { panic(err) } defer c.Close() var wg sync.WaitGroup wg.Add(2) psc := redis.PubSubConn{Conn: c} // This goroutine receives and prints pushed notifications from the server. // The goroutine exits when the connection is unsubscribed from all // channels or there is an error. go func() { defer wg.Done() for { switch n := psc.Receive().(type) { case redis.Message: fmt.Printf("Message: %s %s\n", n.Channel, n.Data) case redis.PMessage: fmt.Printf("PMessage: %s %s %s\n", n.Pattern, n.Channel, n.Data) case redis.Subscription: fmt.Printf("Subscription: %s %s %d\n", n.Kind, n.Channel, n.Count) if n.Count == 0 { return } case error: fmt.Printf("error: %v\n", n) return } } }() // This goroutine manages subscriptions for the connection. go func() { defer wg.Done() psc.Subscribe("example") psc.PSubscribe("p*") // The following function calls publish a message using another // connection to the Redis server. publish("example", "hello") publish("example", "world") publish("pexample", "foo") publish("pexample", "bar") // Unsubscribe from all connections. This will cause the receiving // goroutine to exit. psc.Unsubscribe() psc.PUnsubscribe() }() wg.Wait() // Output: // Subscription: subscribe example 1 // Subscription: psubscribe p* 2 // Message: example hello // Message: example world // PMessage: p* pexample foo // PMessage: p* pexample bar // Subscription: unsubscribe example 1 // Subscription: punsubscribe p* 0 }
func main() { flag.Parse() redisPool := redis.NewPool(func() (redis.Conn, error) { c, err := redis.Dial("tcp", *redisAddress) if err != nil { return nil, err } return c, err }, *maxConnections) defer redisPool.Close() /* c, err := redis.Dial("tcp", ":6379") if err != nil { panic(err) } defer c.Close() */ var wg sync.WaitGroup wg.Add(2) // psc := redis.PubSubConn{Conn: c} psc := redis.PubSubConn{Conn: redisPool.Get()} // This goroutine receives and prints pushed notifications from the server. // The goroutine exits when the connection is unsubscribed from all // channels or there is an error. go func() { defer wg.Done() for { switch n := psc.Receive().(type) { case redis.Message: fmt.Printf("Message: %s %s\n", n.Channel, n.Data) case redis.PMessage: fmt.Printf("PMessage: %s %s %s\n", n.Pattern, n.Channel, n.Data) case redis.Subscription: fmt.Printf("Subscription: %s %s %d\n", n.Kind, n.Channel, n.Count) if n.Count == 0 { return } case error: fmt.Printf("error: %v\n", n) return } } }() // This goroutine manages subscriptions for the connection. go func() { defer wg.Done() psc.Subscribe("example") psc.PSubscribe("p*") psc.PSubscribe("bigbluebutton:to-bbb-apps:system") // The following function calls publish a message using another // connection to the Redis server. publish("example", "hello") publish("example", "world") publish("pexample", "foo") publish("pexample", "bar") // Unsubscribe from all connections. This will cause the receiving // goroutine to exit. psc.Unsubscribe() //psc.PUnsubscribe() }() wg.Wait() // Output: // Subscription: subscribe example 1 // Subscription: psubscribe p* 2 // Message: example hello // Message: example world // PMessage: p* pexample foo // PMessage: p* pexample bar // Subscription: unsubscribe example 1 // Subscription: punsubscribe p* 0 }
func main() { debug := false //bool for now we can make it more verbose if needed handleFlags(&debug) //setup the pool for the connections var pool = &redis.Pool{ MaxIdle: common.REDIS_MAX_POOL_IDLE, IdleTimeout: 240 * time.Second, Dial: func() (redis.Conn, error) { c, err := redis.Dial("tcp", common.REDIS_ADDRESS+":"+common.REDIS_PORT) if err != nil { return nil, err } return c, err }, //end dial } //end pool common.LogEvent(debug, "Created new Redis Pool.") zmqCTX, err := zmq.NewContext() if err != nil { panic(err) } defer zmqCTX.Close() common.LogEvent(debug, "Created new ZeroMQ Context") trackerZMQPUB, err := zmqCTX.Socket(zmq.Pub) if err != nil { panic(err) } defer trackerZMQPUB.Close() common.LogEvent(debug, "Created new ZeroMQ Pub Socket.") trackerZMQREP, err := zmqCTX.Socket(zmq.Rep) if err != nil { panic(err) } defer trackerZMQREP.Close() common.LogEvent(debug, "Created new ZeroMQ Rep Socket.") //bind the publisher socket to the pub port for zmq if err = trackerZMQPUB.Bind(common.ZMQ_SOCKET_PROTOCOL + common.ZMQ_TRACKER_PUB_IP_ADDRESS + ":" + common.ZMQ_TRACKER_PUB_PORT); err != nil { panic(err) } //bind the reply socket to the rep port for zmq if err = trackerZMQREP.Bind(common.ZMQ_SOCKET_PROTOCOL + common.ZMQ_TRACKER_REP_IP_ADDRESS + ":" + common.ZMQ_TRACKER_REP_PORT); err != nil { panic(err) } fmt.Println(pool.ActiveCount()) conn := pool.Get() defer conn.Close() common.LogEvent(debug, "Created a new pool connection") psc := redis.PubSubConn{conn} //setup a PubSubConn passing our previous connection to it psc.PSubscribe(common.REDIS_SUB_STRING) //subscribe to the ASMS::* string, which is everything fmt.Println(pool.ActiveCount()) //channelRegistry := make(map[string]chan string) //create a channelRegistry to track the channels being created below for each spawned goroutine go handleReply(pool, trackerZMQREP) //spawn a go routine for handleReply this takes care of handling responding to server loads common.LogEvent(debug, "Spawned new goprocess for handleReply.") for { common.LogEvent(debug, "Receieved a new redis data item.") switch v := psc.Receive().(type) { case redis.PMessage: common.LogEvent(debug, "Redis data item is of type Message.") channelSplit := strings.Split(v.Channel, common.ACCOUNT_IDS_SEP) //take the channel string contained in the reply struct, split it. switch channelSplit[1] { // the key is laid out as ASMS::<Message>/<Receipt>/<UpdateDevice>::.... case "Message": go handleMessage(pool, trackerZMQPUB, v.Data) common.LogEvent(debug, "Spawned new goprocess for handleMessage.") case "Receipt": go handleReceipt(pool, trackerZMQPUB, v.Data) common.LogEvent(debug, "Spawned new goprocess for handleReceipt.") case "UpdateDevice": go handleUpdateDevice(pool, trackerZMQPUB, v.Data) common.LogEvent(debug, "Spawned new goprocess for handleUpdateDevice.") default: fmt.Println("tracker.go: Recieved an unexpected request.") } //end switch channelSplit[1] case redis.Subscription: //dont know what to say!!! fmt.Println("I guess we will always get here on start,since we recieve back from the redis server?") case error: panic(v) } //end switch v:= } //end for } //end main