@@ -3,6 +3,7 @@ package redis
3
3
import (
4
4
"errors"
5
5
"fmt"
6
+ "strings"
6
7
"sync"
7
8
"time"
8
9
@@ -29,8 +30,9 @@ type PubSub struct {
29
30
cn * pool.Conn
30
31
channels map [string ]struct {}
31
32
patterns map [string ]struct {}
32
- closed bool
33
- exit chan struct {}
33
+
34
+ closed bool
35
+ exit chan struct {}
34
36
35
37
cmd * Cmd
36
38
@@ -39,6 +41,12 @@ type PubSub struct {
39
41
ping chan struct {}
40
42
}
41
43
44
+ func (c * PubSub ) String () string {
45
+ channels := mapKeys (c .channels )
46
+ channels = append (channels , mapKeys (c .patterns )... )
47
+ return fmt .Sprintf ("PubSub(%s)" , strings .Join (channels , ", " ))
48
+ }
49
+
42
50
func (c * PubSub ) init () {
43
51
c .exit = make (chan struct {})
44
52
}
@@ -389,16 +397,23 @@ func (c *PubSub) ReceiveMessage() (*Message, error) {
389
397
// It periodically sends Ping messages to test connection health.
390
398
// The channel is closed with PubSub. Receive* APIs can not be used
391
399
// after channel is created.
400
+ //
401
+ // If the Go channel is full for 30 seconds the message is dropped.
392
402
func (c * PubSub ) Channel () <- chan * Message {
393
403
c .chOnce .Do (c .initChannel )
394
404
return c .ch
395
405
}
396
406
397
407
func (c * PubSub ) initChannel () {
408
+ const timeout = 30 * time .Second
409
+
398
410
c .ch = make (chan * Message , 100 )
399
- c .ping = make (chan struct {}, 10 )
411
+ c .ping = make (chan struct {}, 1 )
400
412
401
413
go func () {
414
+ timer := time .NewTimer (timeout )
415
+ timer .Stop ()
416
+
402
417
var errCount int
403
418
for {
404
419
msg , err := c .Receive ()
@@ -413,6 +428,7 @@ func (c *PubSub) initChannel() {
413
428
errCount ++
414
429
continue
415
430
}
431
+
416
432
errCount = 0
417
433
418
434
// Any message is as good as a ping.
@@ -427,16 +443,24 @@ func (c *PubSub) initChannel() {
427
443
case * Pong :
428
444
// Ignore.
429
445
case * Message :
430
- c .ch <- msg
446
+ timer .Reset (timeout )
447
+ select {
448
+ case c .ch <- msg :
449
+ if ! timer .Stop () {
450
+ <- timer .C
451
+ }
452
+ case <- timer .C :
453
+ internal .Logf (
454
+ "redis: %s channel is full for %s (message is dropped)" ,
455
+ c , timeout )
456
+ }
431
457
default :
432
- internal .Logf ("redis: unknown message: %T" , msg )
458
+ internal .Logf ("redis: unknown message type : %T" , msg )
433
459
}
434
460
}
435
461
}()
436
462
437
463
go func () {
438
- const timeout = 5 * time .Second
439
-
440
464
timer := time .NewTimer (timeout )
441
465
timer .Stop ()
442
466
0 commit comments