Beispiel #1
0
func (logger *RedisLogger) Unsubscribe(psc *redis.PubSubConn, groups ...string) error {
	var channels []interface{}
	for _, group := range groups {
		channels = append(channels, redisPubSubGroup+group)
	}
	return psc.Unsubscribe(channels...)
}
Beispiel #2
0
func slaveHandler(s *websocket.Conn, sessionID int, dbStore *Store, redisAddr string) {
	xlog.Debugf("entering SlaveHandler")
	c, err := redis.Dial("tcp", redisAddr)
	if err != nil {
		xlog.Errorf("redis.Dial failed: %v", err)
		return
	}
	defer c.Close()

	psc := redis.PubSubConn{Conn: c}
	topic := fmt.Sprintf("session.%d", sessionID)
	psc.Subscribe(topic)
	defer psc.Unsubscribe(topic)

	for {
		switch v := psc.Receive().(type) {
		case redis.Message:
			StatCount("command for slave", 1)
			var cmd Command
			if err := json.Unmarshal(v.Data, &cmd); err != nil {
				break
			}
			if err := websocket.JSON.Send(s, cmd); err != nil {
				xlog.Errorf("slaveHandler: JSON.Send failed: %v", err)
				return
			}
			if cmd.Cmd == "close" {
				return
			}
		case redis.Subscription:
			xlog.Debugf("mkay... redis.Subscription received: %#v", v)
		}
	}
}
Beispiel #3
0
// GetTaskResult fetchs task result for the specified taskID
func (b *Broker) GetTaskResult(taskID string) <-chan *broker.Message {
	msg := make(chan *broker.Message)

	// fetch messages
	log.Debug("Waiting for Task Result Messages: ", taskID)
	conn := b.pool.Get()
	psc := redis.PubSubConn{Conn: conn}
	psc.Subscribe(taskID)

	go func() {
		for {
			switch v := psc.Receive().(type) {
			case redis.Message:
				log.Info("message: ", string(v.Data))
				m := &broker.Message{}
				err := json.Unmarshal(v.Data, &m)
				if err != nil {
					log.Error("Failed to unmarshal message.")
				} else {
					log.Debug("Task Result message: ", string(m.Body))
					msg <- m
				}
				psc.Unsubscribe()
				conn.Close()
				close(msg)
				break
			}
		}
	}()
	log.Debug("Subscribed to Task Result")
	return msg
}
Beispiel #4
0
func RedisUnSub(key string, psc redis.PubSubConn) error {
	if err := psc.Unsubscribe(key); err != nil {
		Log.Printf("psc.Unsubscribe(\"%s\") faild (%s)", key, err.Error())
		return err
	}

	return nil
}
Beispiel #5
0
// 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 testPublishChannel(t *testing.T, cfg map[string]interface{}) {
	batches := 100
	batchSize := 1000
	total := batches & batchSize

	db := 0
	index := cfg["index"].(string)
	if v, ok := cfg["db"]; ok {
		db = v.(int)
	}

	conn, err := redis.Dial("tcp", getRedisAddr(), redis.DialDatabase(db))
	if err != nil {
		t.Fatalf("redis.Dial failed %v", err)
	}

	// delete old key if present
	defer conn.Close()
	conn.Do("DEL", index)

	// subscribe to packetbeat channel
	psc := redis.PubSubConn{conn}
	if err := psc.Subscribe(index); err != nil {
		t.Fatal(err)
	}
	defer psc.Unsubscribe(index)

	// connect and publish events
	var wg sync.WaitGroup
	var pubErr error
	out := newRedisTestingOutput(t, cfg)
	wg.Add(1)
	go func() {
		defer wg.Done()
		pubErr = sendTestEvents(out, batches, batchSize)
	}()

	// collect published events by subscription
	var messages [][]byte
	assert.NoError(t, conn.Err())
	for conn.Err() == nil {
		t.Logf("try collect message")

		switch v := psc.Receive().(type) {
		case redis.Message:
			messages = append(messages, v.Data)
		case error:
			t.Error(v)
		default:
			t.Logf("received: %#v", v)
		}

		if len(messages) == total {
			break
		}
	}
	wg.Wait()

	// validate
	assert.NoError(t, pubErr)
	assert.Equal(t, total, len(messages))
	for i, raw := range messages {
		evt := struct{ Message int }{}
		err = json.Unmarshal(raw, &evt)
		assert.NoError(t, err)
		assert.Equal(t, i+1, evt.Message)
	}
}
Beispiel #7
0
func TestPubSub(t *testing.T) {
	conn := NewConn()
	conn.ReceiveWait = true
	redisChannel := "subchannel"

	conn.Command("SUBSCRIBE", redisChannel).Expect([]interface{}{
		[]byte("subscribe"),
		[]byte(redisChannel),
		[]byte("1"),
	})
	messages := [][]byte{
		[]byte("value1"),
		[]byte("value2"),
		[]byte("value3"),
		[]byte("finished"),
	}
	for _, message := range messages {
		conn.AddSubscriptionMessage([]interface{}{
			[]byte("message"),
			[]byte(redisChannel),
			message,
		})
	}
	//Check some values are correct
	if len(conn.commands) != 1 {
		t.Error("Initial subscription message not set correctly")
	}
	if len(conn.SubResponses) != 4 {
		t.Error("PubSub messages not queued up corectly")
	}

	//Use the pub sub connection
	nextMessage := func() {
		conn.ReceiveNow <- true
	}
	go nextMessage() //Allow the subscribe message to come through

	psc := redis.PubSubConn{Conn: conn}
	psc.Subscribe(redisChannel)
	defer psc.Unsubscribe()
	//Receive the subscribe message
	subResponse := psc.Receive()
	switch smsg := subResponse.(type) {
	case redis.Subscription:
		if smsg.Kind != "subscribe" {
			t.Error("Subscription ack kind is wrong")
		}
		if smsg.Channel != redisChannel {
			t.Error("Subscription ack channel is wrong")
		}
		if smsg.Count != 1 {
			t.Error("Subscription ack count is wrong")
		}
	default:
		t.Error("Got wrong type back on initial subscription")
	}
	//Receive the other messages - control when they come
	testResponse := make(chan []byte, 1)
	go func() {
		for {
			switch msg := psc.Receive().(type) {
			case redis.Message:
				testResponse <- msg.Data
			}
		}
	}()
	for _, expMsg := range messages {
		assertChannelEmpty(t, testResponse)
		go nextMessage()
		msg := <-testResponse
		if !reflect.DeepEqual(msg, expMsg) {
			t.Error("Expected message", string(expMsg), "got", string(msg))
		}
		assertChannelEmpty(t, testResponse)
	}
}
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
}
Beispiel #9
0
func (this __red) Subscribe(messages ...interface{}) (notify chan interface{}, shutdown func(wait bool)) {
	log.Println("SUBSCRIBE")

	channels := []interface{}{}
	channelsMap := map[string]interface{}{}
	for _, message := range messages {
		switch message := message.(type) {

		default:
			_ = message
			panic("Unsupported message type")
		}
	}

	conn := this.__.(redis.Conn)
	psc := redis.PubSubConn{Conn: conn}

	err := psc.Subscribe(channels...)
	if err != nil {
		panic(err)
	}

	notify = make(chan interface{}, 1024)
	notifyInternal := make(chan interface{}, 1024)
	closeInternal := make(chan error, 1)

	go func() {
		defer func() {
			if rec := recover(); rec != nil {
				log.Println("PANIC ! RECEIVER:", rec, __red_stack())
				closeInternal <- errors.New(fmt.Sprint(rec))
			} else {
				log.Println("RECEIVER No more subscriptions")
				closeInternal <- nil
			}
		}()

		for {
			switch n := psc.Receive().(type) {
			case redis.Message:
				if m, ok := channelsMap[n.Channel]; ok {
					switch m := m.(type) {

					default:
						_ = m
						panic("Unsupported message type")
					}
				} else {
					// TODO
				}
			case redis.Subscription:
				if n.Count == 0 {
					return
				}
			}
		}
	}()

	var doneWG sync.WaitGroup
	doneWG.Add(1)
	go func() {
		defer func() {
			defer doneWG.Done()
			if rec := recover(); rec != nil {
				log.Println("PANIC ! PINGER:", rec, __red_stack())
				notify <- errors.New(fmt.Sprint(rec))
			} else {
				// TODO
				log.Println("PUBSUB | CLOSED")
			}
		}()
	Q:
		for {
			select {
			case err := <-closeInternal:
				notify <- err
				break Q
			case <-notifyInternal:
				// notify <- msg
			case <-time.After(__red_ops.PingPeriod):
				err := psc.Ping("")
				if err != nil {
					notify <- err
					break Q
				}
			}
		}
	}()

	shutdown = func(wait bool) {
		err := psc.Unsubscribe()
		if err != nil {
			panic(err)
		}
		if wait {
			doneWG.Wait()
		}
	}
	return
}