@@ -567,4 +567,104 @@ var _ = Describe("PubSub", func() {
567567 Expect (msg .Channel ).To (Equal ("mychannel" ))
568568 Expect (msg .Payload ).To (Equal (text ))
569569 })
570+
571+ It ("should not use connections from pool" , func () {
572+ statsBefore := client .PoolStats ()
573+
574+ pubsub := client .Subscribe (ctx , "mychannel" )
575+ defer pubsub .Close ()
576+
577+ stats := client .PoolStats ()
578+ // A connection has been created
579+ Expect (stats .TotalConns - statsBefore .TotalConns ).To (Equal (uint32 (1 )))
580+ // But it's not taken from the pool
581+ poolFetchesBefore := statsBefore .Hits + statsBefore .Misses
582+ poolFetchesAfter := stats .Hits + stats .Misses
583+ Expect (poolFetchesAfter - poolFetchesBefore ).To (Equal (uint32 (0 )))
584+
585+ pubsub .Close ()
586+
587+ stats = client .PoolStats ()
588+ // The connection no longer exists
589+ Expect (stats .TotalConns - statsBefore .TotalConns ).To (Equal (uint32 (0 )))
590+ Expect (stats .IdleConns - statsBefore .IdleConns ).To (Equal (uint32 (0 )))
591+ })
592+ })
593+
594+ var _ = Describe ("PubSub with PubsubFromPool set" , func () {
595+ var client * redis.Client
596+
597+ BeforeEach (func () {
598+ opt := redisOptions ()
599+ opt .MinIdleConns = 0
600+ opt .ConnMaxLifetime = 0
601+ opt .PubsubFromPool = true
602+ // zero value ends up using default so set small instead
603+ opt .PoolTimeout = time .Microsecond
604+ client = redis .NewClient (opt )
605+ Expect (client .FlushDB (ctx ).Err ()).NotTo (HaveOccurred ())
606+ })
607+
608+ AfterEach (func () {
609+ Expect (client .Close ()).NotTo (HaveOccurred ())
610+ })
611+
612+ It ("should use connection from pool" , func () {
613+ statsBefore := client .PoolStats ()
614+
615+ pubsub := client .Subscribe (ctx , "mychannel" )
616+ defer pubsub .Close ()
617+
618+ stats := client .PoolStats ()
619+ // A connection has been taken from the pool
620+ Expect (stats .Hits - statsBefore .Hits ).To (Equal (uint32 (1 )))
621+ statsDuring := client .PoolStats ()
622+
623+ pubsub .Close ()
624+
625+ stats = client .PoolStats ()
626+ // It's not returned to the idle pool ..
627+ Expect (statsDuring .IdleConns - stats .IdleConns ).To (Equal (uint32 (0 )))
628+ // .. and has been terminated
629+ Expect (statsDuring .TotalConns - stats .TotalConns ).To (Equal (uint32 (1 )))
630+ })
631+
632+ It ("should respect pool size limit" , func () {
633+ poolSize := client .Options ().PoolSize
634+ statsBefore := client .PoolStats ()
635+
636+ var pubsubs []* redis.PubSub
637+ for i := 0 ; i < poolSize ; i ++ {
638+ pubsub := client .Subscribe (ctx , "mychannel" )
639+ defer pubsub .Close ()
640+ pubsubs = append (pubsubs , pubsub )
641+ }
642+
643+ statsDuring := client .PoolStats ()
644+ poolFetchesBefore := statsBefore .Hits + statsBefore .Misses
645+ poolFetchesAfter := statsDuring .Hits + statsDuring .Misses
646+
647+ // A total of poolSize connections should have been taken from the pool (new or existing)
648+ Expect (poolFetchesAfter - poolFetchesBefore ).To (Equal (uint32 (poolSize )))
649+
650+ // The next pubsub connection should fail to connect (waiting for pool)
651+ extraPubsub := client .Subscribe (ctx , "mychannel" )
652+ defer extraPubsub .Close ()
653+ Expect (client .PoolStats ().Timeouts - statsDuring .Timeouts ).To (Equal (uint32 (1 )))
654+
655+ // As should retries
656+ err := extraPubsub .Ping (ctx )
657+ Expect (err ).To (MatchError (ContainSubstring ("connection pool timeout" )))
658+ Expect (client .PoolStats ().Timeouts - statsDuring .Timeouts ).To (Equal (uint32 (2 )))
659+
660+ for _ , pubsub := range pubsubs {
661+ pubsub .Close ()
662+ }
663+
664+ stats := client .PoolStats ()
665+ // Connections are not returned to the idle pool ..
666+ Expect (statsDuring .IdleConns - stats .IdleConns ).To (Equal (uint32 (0 )))
667+ // .. and have been terminated
668+ Expect (statsDuring .TotalConns - stats .TotalConns ).To (Equal (uint32 (poolSize )))
669+ })
570670})
0 commit comments