redis/pubsub_test.go

379 lines
9.7 KiB
Go
Raw Normal View History

2015-01-15 18:51:22 +03:00
package redis_test
import (
"io"
2015-01-15 18:51:22 +03:00
"net"
2015-11-22 15:44:38 +03:00
"sync"
2015-01-15 18:51:22 +03:00
"time"
2017-02-18 17:42:34 +03:00
"github.com/go-redis/redis"
2017-02-18 13:28:01 +03:00
2015-01-15 18:51:22 +03:00
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("PubSub", func() {
var client *redis.Client
BeforeEach(func() {
client = redis.NewClient(redisOptions())
2015-07-11 13:12:47 +03:00
Expect(client.FlushDb().Err()).NotTo(HaveOccurred())
2015-01-15 18:51:22 +03:00
})
AfterEach(func() {
Expect(client.Close()).NotTo(HaveOccurred())
})
It("should support pattern matching", func() {
2017-04-11 16:53:55 +03:00
pubsub := client.PSubscribe("mychannel*")
2015-07-11 13:42:44 +03:00
defer pubsub.Close()
2015-01-15 18:51:22 +03:00
{
msgi, err := pubsub.ReceiveTimeout(time.Second)
Expect(err).NotTo(HaveOccurred())
subscr := msgi.(*redis.Subscription)
Expect(subscr.Kind).To(Equal("psubscribe"))
Expect(subscr.Channel).To(Equal("mychannel*"))
Expect(subscr.Count).To(Equal(1))
}
{
msgi, err := pubsub.ReceiveTimeout(time.Second)
Expect(err.(net.Error).Timeout()).To(Equal(true))
Expect(msgi).To(BeNil())
}
n, err := client.Publish("mychannel1", "hello").Result()
Expect(err).NotTo(HaveOccurred())
Expect(n).To(Equal(int64(1)))
Expect(pubsub.PUnsubscribe("mychannel*")).NotTo(HaveOccurred())
2015-01-15 18:51:22 +03:00
{
msgi, err := pubsub.ReceiveTimeout(time.Second)
Expect(err).NotTo(HaveOccurred())
2016-04-09 11:45:56 +03:00
subscr := msgi.(*redis.Message)
2015-01-15 18:51:22 +03:00
Expect(subscr.Channel).To(Equal("mychannel1"))
Expect(subscr.Pattern).To(Equal("mychannel*"))
Expect(subscr.Payload).To(Equal("hello"))
}
{
msgi, err := pubsub.ReceiveTimeout(time.Second)
Expect(err).NotTo(HaveOccurred())
subscr := msgi.(*redis.Subscription)
Expect(subscr.Kind).To(Equal("punsubscribe"))
Expect(subscr.Channel).To(Equal("mychannel*"))
Expect(subscr.Count).To(Equal(0))
}
2016-03-17 19:00:47 +03:00
stats := client.PoolStats()
2016-04-09 11:45:56 +03:00
Expect(stats.Requests - stats.Hits).To(Equal(uint32(2)))
2015-01-15 18:51:22 +03:00
})
It("should pub/sub channels", func() {
channels, err := client.PubSubChannels("mychannel*").Result()
Expect(err).NotTo(HaveOccurred())
Expect(channels).To(BeEmpty())
2017-04-11 16:53:55 +03:00
pubsub := client.Subscribe("mychannel", "mychannel2")
2015-07-11 13:42:44 +03:00
defer pubsub.Close()
2015-01-15 18:51:22 +03:00
channels, err = client.PubSubChannels("mychannel*").Result()
Expect(err).NotTo(HaveOccurred())
Expect(channels).To(ConsistOf([]string{"mychannel", "mychannel2"}))
channels, err = client.PubSubChannels("").Result()
Expect(err).NotTo(HaveOccurred())
Expect(channels).To(BeEmpty())
channels, err = client.PubSubChannels("*").Result()
Expect(err).NotTo(HaveOccurred())
Expect(len(channels)).To(BeNumerically(">=", 2))
})
It("should return the numbers of subscribers", func() {
2017-04-11 16:53:55 +03:00
pubsub := client.Subscribe("mychannel", "mychannel2")
2015-07-11 13:42:44 +03:00
defer pubsub.Close()
2015-01-15 18:51:22 +03:00
channels, err := client.PubSubNumSub("mychannel", "mychannel2", "mychannel3").Result()
Expect(err).NotTo(HaveOccurred())
2015-01-25 15:05:19 +03:00
Expect(channels).To(Equal(map[string]int64{
"mychannel": 1,
"mychannel2": 1,
"mychannel3": 0,
2015-01-15 18:51:22 +03:00
}))
})
It("should return the numbers of subscribers by pattern", func() {
num, err := client.PubSubNumPat().Result()
Expect(err).NotTo(HaveOccurred())
Expect(num).To(Equal(int64(0)))
2017-04-11 16:53:55 +03:00
pubsub := client.PSubscribe("*")
2015-07-11 13:42:44 +03:00
defer pubsub.Close()
2015-01-15 18:51:22 +03:00
num, err = client.PubSubNumPat().Result()
Expect(err).NotTo(HaveOccurred())
Expect(num).To(Equal(int64(1)))
})
It("should pub/sub", func() {
2017-04-11 16:53:55 +03:00
pubsub := client.Subscribe("mychannel", "mychannel2")
2015-07-11 13:42:44 +03:00
defer pubsub.Close()
2015-01-15 18:51:22 +03:00
{
msgi, err := pubsub.ReceiveTimeout(time.Second)
Expect(err).NotTo(HaveOccurred())
subscr := msgi.(*redis.Subscription)
Expect(subscr.Kind).To(Equal("subscribe"))
Expect(subscr.Channel).To(Equal("mychannel"))
Expect(subscr.Count).To(Equal(1))
}
{
msgi, err := pubsub.ReceiveTimeout(time.Second)
Expect(err).NotTo(HaveOccurred())
subscr := msgi.(*redis.Subscription)
Expect(subscr.Kind).To(Equal("subscribe"))
Expect(subscr.Channel).To(Equal("mychannel2"))
Expect(subscr.Count).To(Equal(2))
}
{
msgi, err := pubsub.ReceiveTimeout(time.Second)
Expect(err.(net.Error).Timeout()).To(Equal(true))
Expect(msgi).NotTo(HaveOccurred())
}
n, err := client.Publish("mychannel", "hello").Result()
Expect(err).NotTo(HaveOccurred())
Expect(n).To(Equal(int64(1)))
n, err = client.Publish("mychannel2", "hello2").Result()
Expect(err).NotTo(HaveOccurred())
Expect(n).To(Equal(int64(1)))
Expect(pubsub.Unsubscribe("mychannel", "mychannel2")).NotTo(HaveOccurred())
2015-01-15 18:51:22 +03:00
{
msgi, err := pubsub.ReceiveTimeout(time.Second)
Expect(err).NotTo(HaveOccurred())
subscr := msgi.(*redis.Message)
Expect(subscr.Channel).To(Equal("mychannel"))
Expect(subscr.Payload).To(Equal("hello"))
}
{
msgi, err := pubsub.ReceiveTimeout(time.Second)
Expect(err).NotTo(HaveOccurred())
msg := msgi.(*redis.Message)
Expect(msg.Channel).To(Equal("mychannel2"))
Expect(msg.Payload).To(Equal("hello2"))
}
{
msgi, err := pubsub.ReceiveTimeout(time.Second)
Expect(err).NotTo(HaveOccurred())
subscr := msgi.(*redis.Subscription)
Expect(subscr.Kind).To(Equal("unsubscribe"))
Expect(subscr.Channel).To(Equal("mychannel"))
Expect(subscr.Count).To(Equal(1))
}
{
msgi, err := pubsub.ReceiveTimeout(time.Second)
Expect(err).NotTo(HaveOccurred())
subscr := msgi.(*redis.Subscription)
Expect(subscr.Kind).To(Equal("unsubscribe"))
Expect(subscr.Channel).To(Equal("mychannel2"))
Expect(subscr.Count).To(Equal(0))
}
2016-03-17 19:00:47 +03:00
stats := client.PoolStats()
2016-04-09 11:45:56 +03:00
Expect(stats.Requests - stats.Hits).To(Equal(uint32(2)))
2015-01-15 18:51:22 +03:00
})
2015-07-11 13:12:47 +03:00
It("should ping/pong", func() {
2017-04-11 16:53:55 +03:00
pubsub := client.Subscribe("mychannel")
2015-07-11 13:42:44 +03:00
defer pubsub.Close()
2015-07-11 13:12:47 +03:00
2017-04-11 16:53:55 +03:00
_, err := pubsub.ReceiveTimeout(time.Second)
2015-07-11 13:12:47 +03:00
Expect(err).NotTo(HaveOccurred())
err = pubsub.Ping("")
Expect(err).NotTo(HaveOccurred())
msgi, err := pubsub.ReceiveTimeout(time.Second)
Expect(err).NotTo(HaveOccurred())
pong := msgi.(*redis.Pong)
Expect(pong.Payload).To(Equal(""))
})
It("should ping/pong with payload", func() {
2017-04-11 16:53:55 +03:00
pubsub := client.Subscribe("mychannel")
2015-07-11 13:42:44 +03:00
defer pubsub.Close()
2015-07-11 13:12:47 +03:00
2017-04-11 16:53:55 +03:00
_, err := pubsub.ReceiveTimeout(time.Second)
2015-07-11 13:12:47 +03:00
Expect(err).NotTo(HaveOccurred())
err = pubsub.Ping("hello")
Expect(err).NotTo(HaveOccurred())
msgi, err := pubsub.ReceiveTimeout(time.Second)
Expect(err).NotTo(HaveOccurred())
pong := msgi.(*redis.Pong)
Expect(pong.Payload).To(Equal("hello"))
})
It("should multi-ReceiveMessage", func() {
2017-04-11 16:53:55 +03:00
pubsub := client.Subscribe("mychannel")
2015-09-06 13:50:16 +03:00
defer pubsub.Close()
2017-04-11 16:53:55 +03:00
err := client.Publish("mychannel", "hello").Err()
Expect(err).NotTo(HaveOccurred())
err = client.Publish("mychannel", "world").Err()
Expect(err).NotTo(HaveOccurred())
msg, err := pubsub.ReceiveMessage()
Expect(err).NotTo(HaveOccurred())
Expect(msg.Channel).To(Equal("mychannel"))
Expect(msg.Payload).To(Equal("hello"))
msg, err = pubsub.ReceiveMessage()
Expect(err).NotTo(HaveOccurred())
Expect(msg.Channel).To(Equal("mychannel"))
Expect(msg.Payload).To(Equal("world"))
})
It("should ReceiveMessage after timeout", func() {
2016-04-09 14:52:01 +03:00
timeout := 100 * time.Millisecond
2016-03-17 19:00:47 +03:00
2017-04-11 16:53:55 +03:00
pubsub := client.Subscribe("mychannel")
defer pubsub.Close()
done := make(chan bool, 1)
2015-09-06 13:50:16 +03:00
go func() {
defer GinkgoRecover()
defer func() {
done <- true
}()
2015-09-06 13:50:16 +03:00
2016-03-17 19:00:47 +03:00
time.Sleep(timeout + 100*time.Millisecond)
2015-09-06 13:50:16 +03:00
n, err := client.Publish("mychannel", "hello").Result()
Expect(err).NotTo(HaveOccurred())
Expect(n).To(Equal(int64(1)))
}()
2016-04-09 14:52:01 +03:00
msg, err := pubsub.ReceiveMessageTimeout(timeout)
2015-09-06 13:50:16 +03:00
Expect(err).NotTo(HaveOccurred())
Expect(msg.Channel).To(Equal("mychannel"))
Expect(msg.Payload).To(Equal("hello"))
2015-11-26 18:04:26 +03:00
Eventually(done).Should(Receive())
2016-03-17 19:00:47 +03:00
stats := client.PoolStats()
Expect(stats.Requests).To(Equal(uint32(3)))
Expect(stats.Hits).To(Equal(uint32(1)))
2015-09-06 13:50:16 +03:00
})
expectReceiveMessageOnError := func(pubsub *redis.PubSub) {
cn, _, err := pubsub.Pool().Get()
2015-09-06 13:50:16 +03:00
Expect(err).NotTo(HaveOccurred())
cn.SetNetConn(&badConn{
readErr: io.EOF,
writeErr: io.EOF,
})
pubsub.Pool().Put(cn)
2015-09-06 13:50:16 +03:00
done := make(chan bool, 1)
2015-09-06 13:50:16 +03:00
go func() {
defer GinkgoRecover()
defer func() {
done <- true
}()
2015-09-06 13:50:16 +03:00
time.Sleep(100 * time.Millisecond)
2015-11-22 15:44:38 +03:00
err := client.Publish("mychannel", "hello").Err()
2015-09-06 13:50:16 +03:00
Expect(err).NotTo(HaveOccurred())
}()
msg, err := pubsub.ReceiveMessage()
Expect(err).NotTo(HaveOccurred())
Expect(msg.Channel).To(Equal("mychannel"))
Expect(msg.Payload).To(Equal("hello"))
2015-11-22 15:44:38 +03:00
Eventually(done).Should(Receive())
2016-03-17 19:00:47 +03:00
stats := client.PoolStats()
Expect(stats.Requests).To(Equal(uint32(4)))
2016-03-17 19:00:47 +03:00
Expect(stats.Hits).To(Equal(uint32(1)))
}
It("Subscribe should reconnect on ReceiveMessage error", func() {
2017-04-11 16:53:55 +03:00
pubsub := client.Subscribe("mychannel")
defer pubsub.Close()
expectReceiveMessageOnError(pubsub)
})
It("PSubscribe should reconnect on ReceiveMessage error", func() {
2017-04-11 16:53:55 +03:00
pubsub := client.PSubscribe("mychannel")
defer pubsub.Close()
expectReceiveMessageOnError(pubsub)
2015-09-06 13:50:16 +03:00
})
2015-12-02 16:40:44 +03:00
It("should return on Close", func() {
2017-04-11 16:53:55 +03:00
pubsub := client.Subscribe("mychannel")
2015-11-26 18:04:26 +03:00
defer pubsub.Close()
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer GinkgoRecover()
wg.Done()
defer wg.Done()
2015-12-02 16:40:44 +03:00
2017-02-18 13:28:01 +03:00
_, err := pubsub.ReceiveMessage()
Expect(err).To(HaveOccurred())
Expect(err).To(SatisfyAny(
MatchError("redis: client is closed"),
MatchError("use of closed network connection"), // Go 1.4
))
2015-11-26 18:04:26 +03:00
}()
2015-12-02 16:40:44 +03:00
2015-11-26 18:04:26 +03:00
wg.Wait()
2015-12-02 16:40:44 +03:00
wg.Add(1)
2015-11-26 18:04:26 +03:00
2017-04-11 16:53:55 +03:00
Expect(pubsub.Close()).NotTo(HaveOccurred())
2015-12-02 16:40:44 +03:00
wg.Wait()
2015-11-26 18:04:26 +03:00
})
It("should ReceiveMessage without a subscription", func() {
timeout := 100 * time.Millisecond
2017-04-11 16:53:55 +03:00
pubsub := client.Subscribe()
defer pubsub.Close()
go func() {
defer GinkgoRecover()
time.Sleep(2 * timeout)
2017-04-11 16:53:55 +03:00
err := pubsub.Subscribe("mychannel")
Expect(err).NotTo(HaveOccurred())
2017-04-11 16:53:55 +03:00
err = client.Publish("mychannel", "hello").Err()
Expect(err).NotTo(HaveOccurred())
}()
msg, err := pubsub.ReceiveMessageTimeout(timeout)
Expect(err).NotTo(HaveOccurred())
Expect(msg.Channel).To(Equal("mychannel"))
Expect(msg.Payload).To(Equal("hello"))
})
2015-01-15 18:51:22 +03:00
})