pubsub.tcl 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. start_server {tags {"pubsub network"}} {
  2. if {$::singledb} {
  3. set db 0
  4. } else {
  5. set db 9
  6. }
  7. test "Pub/Sub PING" {
  8. set rd1 [redis_deferring_client]
  9. subscribe $rd1 somechannel
  10. # While subscribed to non-zero channels PING works in Pub/Sub mode.
  11. $rd1 ping
  12. $rd1 ping "foo"
  13. set reply1 [$rd1 read]
  14. set reply2 [$rd1 read]
  15. unsubscribe $rd1 somechannel
  16. # Now we are unsubscribed, PING should just return PONG.
  17. $rd1 ping
  18. set reply3 [$rd1 read]
  19. $rd1 close
  20. list $reply1 $reply2 $reply3
  21. } {{pong {}} {pong foo} PONG}
  22. test "PUBLISH/SUBSCRIBE basics" {
  23. set rd1 [redis_deferring_client]
  24. # subscribe to two channels
  25. assert_equal {1 2} [subscribe $rd1 {chan1 chan2}]
  26. assert_equal 1 [r publish chan1 hello]
  27. assert_equal 1 [r publish chan2 world]
  28. assert_equal {message chan1 hello} [$rd1 read]
  29. assert_equal {message chan2 world} [$rd1 read]
  30. # unsubscribe from one of the channels
  31. unsubscribe $rd1 {chan1}
  32. assert_equal 0 [r publish chan1 hello]
  33. assert_equal 1 [r publish chan2 world]
  34. assert_equal {message chan2 world} [$rd1 read]
  35. # unsubscribe from the remaining channel
  36. unsubscribe $rd1 {chan2}
  37. assert_equal 0 [r publish chan1 hello]
  38. assert_equal 0 [r publish chan2 world]
  39. # clean up clients
  40. $rd1 close
  41. }
  42. test "PUBLISH/SUBSCRIBE with two clients" {
  43. set rd1 [redis_deferring_client]
  44. set rd2 [redis_deferring_client]
  45. assert_equal {1} [subscribe $rd1 {chan1}]
  46. assert_equal {1} [subscribe $rd2 {chan1}]
  47. assert_equal 2 [r publish chan1 hello]
  48. assert_equal {message chan1 hello} [$rd1 read]
  49. assert_equal {message chan1 hello} [$rd2 read]
  50. # clean up clients
  51. $rd1 close
  52. $rd2 close
  53. }
  54. test "PUBLISH/SUBSCRIBE after UNSUBSCRIBE without arguments" {
  55. set rd1 [redis_deferring_client]
  56. assert_equal {1 2 3} [subscribe $rd1 {chan1 chan2 chan3}]
  57. unsubscribe $rd1
  58. assert_equal 0 [r publish chan1 hello]
  59. assert_equal 0 [r publish chan2 hello]
  60. assert_equal 0 [r publish chan3 hello]
  61. # clean up clients
  62. $rd1 close
  63. }
  64. test "SUBSCRIBE to one channel more than once" {
  65. set rd1 [redis_deferring_client]
  66. assert_equal {1 1 1} [subscribe $rd1 {chan1 chan1 chan1}]
  67. assert_equal 1 [r publish chan1 hello]
  68. assert_equal {message chan1 hello} [$rd1 read]
  69. # clean up clients
  70. $rd1 close
  71. }
  72. test "UNSUBSCRIBE from non-subscribed channels" {
  73. set rd1 [redis_deferring_client]
  74. assert_equal {0 0 0} [unsubscribe $rd1 {foo bar quux}]
  75. # clean up clients
  76. $rd1 close
  77. }
  78. test "PUBLISH/PSUBSCRIBE basics" {
  79. set rd1 [redis_deferring_client]
  80. # subscribe to two patterns
  81. assert_equal {1 2} [psubscribe $rd1 {foo.* bar.*}]
  82. assert_equal 1 [r publish foo.1 hello]
  83. assert_equal 1 [r publish bar.1 hello]
  84. assert_equal 0 [r publish foo1 hello]
  85. assert_equal 0 [r publish barfoo.1 hello]
  86. assert_equal 0 [r publish qux.1 hello]
  87. assert_equal {pmessage foo.* foo.1 hello} [$rd1 read]
  88. assert_equal {pmessage bar.* bar.1 hello} [$rd1 read]
  89. # unsubscribe from one of the patterns
  90. assert_equal {1} [punsubscribe $rd1 {foo.*}]
  91. assert_equal 0 [r publish foo.1 hello]
  92. assert_equal 1 [r publish bar.1 hello]
  93. assert_equal {pmessage bar.* bar.1 hello} [$rd1 read]
  94. # unsubscribe from the remaining pattern
  95. assert_equal {0} [punsubscribe $rd1 {bar.*}]
  96. assert_equal 0 [r publish foo.1 hello]
  97. assert_equal 0 [r publish bar.1 hello]
  98. # clean up clients
  99. $rd1 close
  100. }
  101. test "PUBLISH/PSUBSCRIBE with two clients" {
  102. set rd1 [redis_deferring_client]
  103. set rd2 [redis_deferring_client]
  104. assert_equal {1} [psubscribe $rd1 {chan.*}]
  105. assert_equal {1} [psubscribe $rd2 {chan.*}]
  106. assert_equal 2 [r publish chan.foo hello]
  107. assert_equal {pmessage chan.* chan.foo hello} [$rd1 read]
  108. assert_equal {pmessage chan.* chan.foo hello} [$rd2 read]
  109. # clean up clients
  110. $rd1 close
  111. $rd2 close
  112. }
  113. test "PUBLISH/PSUBSCRIBE after PUNSUBSCRIBE without arguments" {
  114. set rd1 [redis_deferring_client]
  115. assert_equal {1 2 3} [psubscribe $rd1 {chan1.* chan2.* chan3.*}]
  116. punsubscribe $rd1
  117. assert_equal 0 [r publish chan1.hi hello]
  118. assert_equal 0 [r publish chan2.hi hello]
  119. assert_equal 0 [r publish chan3.hi hello]
  120. # clean up clients
  121. $rd1 close
  122. }
  123. test "PUNSUBSCRIBE from non-subscribed channels" {
  124. set rd1 [redis_deferring_client]
  125. assert_equal {0 0 0} [punsubscribe $rd1 {foo.* bar.* quux.*}]
  126. # clean up clients
  127. $rd1 close
  128. }
  129. test "NUMSUB returns numbers, not strings (#1561)" {
  130. r pubsub numsub abc def
  131. } {abc 0 def 0}
  132. test "NUMPATs returns the number of unique patterns" {
  133. set rd1 [redis_deferring_client]
  134. set rd2 [redis_deferring_client]
  135. # Three unique patterns and one that overlaps
  136. psubscribe $rd1 "foo*"
  137. psubscribe $rd2 "foo*"
  138. psubscribe $rd1 "bar*"
  139. psubscribe $rd2 "baz*"
  140. set patterns [r pubsub numpat]
  141. # clean up clients
  142. punsubscribe $rd1
  143. punsubscribe $rd2
  144. assert_equal 3 $patterns
  145. }
  146. test "Mix SUBSCRIBE and PSUBSCRIBE" {
  147. set rd1 [redis_deferring_client]
  148. assert_equal {1} [subscribe $rd1 {foo.bar}]
  149. assert_equal {2} [psubscribe $rd1 {foo.*}]
  150. assert_equal 2 [r publish foo.bar hello]
  151. assert_equal {message foo.bar hello} [$rd1 read]
  152. assert_equal {pmessage foo.* foo.bar hello} [$rd1 read]
  153. # clean up clients
  154. $rd1 close
  155. }
  156. test "PUNSUBSCRIBE and UNSUBSCRIBE should always reply" {
  157. # Make sure we are not subscribed to any channel at all.
  158. r punsubscribe
  159. r unsubscribe
  160. # Now check if the commands still reply correctly.
  161. set reply1 [r punsubscribe]
  162. set reply2 [r unsubscribe]
  163. concat $reply1 $reply2
  164. } {punsubscribe {} 0 unsubscribe {} 0}
  165. ### Keyspace events notification tests
  166. test "Keyspace notifications: we receive keyspace notifications" {
  167. r config set notify-keyspace-events KA
  168. set rd1 [redis_deferring_client]
  169. assert_equal {1} [psubscribe $rd1 *]
  170. r set foo bar
  171. assert_equal "pmessage * __keyspace@${db}__:foo set" [$rd1 read]
  172. $rd1 close
  173. }
  174. test "Keyspace notifications: we receive keyevent notifications" {
  175. r config set notify-keyspace-events EA
  176. set rd1 [redis_deferring_client]
  177. assert_equal {1} [psubscribe $rd1 *]
  178. r set foo bar
  179. assert_equal "pmessage * __keyevent@${db}__:set foo" [$rd1 read]
  180. $rd1 close
  181. }
  182. test "Keyspace notifications: we can receive both kind of events" {
  183. r config set notify-keyspace-events KEA
  184. set rd1 [redis_deferring_client]
  185. assert_equal {1} [psubscribe $rd1 *]
  186. r set foo bar
  187. assert_equal "pmessage * __keyspace@${db}__:foo set" [$rd1 read]
  188. assert_equal "pmessage * __keyevent@${db}__:set foo" [$rd1 read]
  189. $rd1 close
  190. }
  191. test "Keyspace notifications: we are able to mask events" {
  192. r config set notify-keyspace-events KEl
  193. r del mylist
  194. set rd1 [redis_deferring_client]
  195. assert_equal {1} [psubscribe $rd1 *]
  196. r set foo bar
  197. r lpush mylist a
  198. # No notification for set, because only list commands are enabled.
  199. assert_equal "pmessage * __keyspace@${db}__:mylist lpush" [$rd1 read]
  200. assert_equal "pmessage * __keyevent@${db}__:lpush mylist" [$rd1 read]
  201. $rd1 close
  202. }
  203. test "Keyspace notifications: general events test" {
  204. r config set notify-keyspace-events KEg
  205. set rd1 [redis_deferring_client]
  206. assert_equal {1} [psubscribe $rd1 *]
  207. r set foo bar
  208. r expire foo 1
  209. r del foo
  210. assert_equal "pmessage * __keyspace@${db}__:foo expire" [$rd1 read]
  211. assert_equal "pmessage * __keyevent@${db}__:expire foo" [$rd1 read]
  212. assert_equal "pmessage * __keyspace@${db}__:foo del" [$rd1 read]
  213. assert_equal "pmessage * __keyevent@${db}__:del foo" [$rd1 read]
  214. $rd1 close
  215. }
  216. test "Keyspace notifications: list events test" {
  217. r config set notify-keyspace-events KEl
  218. r del mylist
  219. set rd1 [redis_deferring_client]
  220. assert_equal {1} [psubscribe $rd1 *]
  221. r lpush mylist a
  222. r rpush mylist a
  223. r rpop mylist
  224. assert_equal "pmessage * __keyspace@${db}__:mylist lpush" [$rd1 read]
  225. assert_equal "pmessage * __keyevent@${db}__:lpush mylist" [$rd1 read]
  226. assert_equal "pmessage * __keyspace@${db}__:mylist rpush" [$rd1 read]
  227. assert_equal "pmessage * __keyevent@${db}__:rpush mylist" [$rd1 read]
  228. assert_equal "pmessage * __keyspace@${db}__:mylist rpop" [$rd1 read]
  229. assert_equal "pmessage * __keyevent@${db}__:rpop mylist" [$rd1 read]
  230. $rd1 close
  231. }
  232. test "Keyspace notifications: set events test" {
  233. r config set notify-keyspace-events Ks
  234. r del myset
  235. set rd1 [redis_deferring_client]
  236. assert_equal {1} [psubscribe $rd1 *]
  237. r sadd myset a b c d
  238. r srem myset x
  239. r sadd myset x y z
  240. r srem myset x
  241. assert_equal "pmessage * __keyspace@${db}__:myset sadd" [$rd1 read]
  242. assert_equal "pmessage * __keyspace@${db}__:myset sadd" [$rd1 read]
  243. assert_equal "pmessage * __keyspace@${db}__:myset srem" [$rd1 read]
  244. $rd1 close
  245. }
  246. test "Keyspace notifications: zset events test" {
  247. r config set notify-keyspace-events Kz
  248. r del myzset
  249. set rd1 [redis_deferring_client]
  250. assert_equal {1} [psubscribe $rd1 *]
  251. r zadd myzset 1 a 2 b
  252. r zrem myzset x
  253. r zadd myzset 3 x 4 y 5 z
  254. r zrem myzset x
  255. assert_equal "pmessage * __keyspace@${db}__:myzset zadd" [$rd1 read]
  256. assert_equal "pmessage * __keyspace@${db}__:myzset zadd" [$rd1 read]
  257. assert_equal "pmessage * __keyspace@${db}__:myzset zrem" [$rd1 read]
  258. $rd1 close
  259. }
  260. test "Keyspace notifications: hash events test" {
  261. r config set notify-keyspace-events Kh
  262. r del myhash
  263. set rd1 [redis_deferring_client]
  264. assert_equal {1} [psubscribe $rd1 *]
  265. r hmset myhash yes 1 no 0
  266. r hincrby myhash yes 10
  267. assert_equal "pmessage * __keyspace@${db}__:myhash hset" [$rd1 read]
  268. assert_equal "pmessage * __keyspace@${db}__:myhash hincrby" [$rd1 read]
  269. $rd1 close
  270. }
  271. test "Keyspace notifications: stream events test" {
  272. r config set notify-keyspace-events Kt
  273. r del mystream
  274. set rd1 [redis_deferring_client]
  275. assert_equal {1} [psubscribe $rd1 *]
  276. r xgroup create mystream mygroup $ mkstream
  277. r xgroup createconsumer mystream mygroup Bob
  278. set id [r xadd mystream 1 field1 A]
  279. r xreadgroup group mygroup Alice STREAMS mystream >
  280. r xclaim mystream mygroup Mike 0 $id force
  281. # Not notify because of "Lee" not exists.
  282. r xgroup delconsumer mystream mygroup Lee
  283. # Not notify because of "Bob" exists.
  284. r xautoclaim mystream mygroup Bob 0 $id
  285. r xgroup delconsumer mystream mygroup Bob
  286. assert_equal "pmessage * __keyspace@${db}__:mystream xgroup-create" [$rd1 read]
  287. assert_equal "pmessage * __keyspace@${db}__:mystream xgroup-createconsumer" [$rd1 read]
  288. assert_equal "pmessage * __keyspace@${db}__:mystream xadd" [$rd1 read]
  289. assert_equal "pmessage * __keyspace@${db}__:mystream xgroup-createconsumer" [$rd1 read]
  290. assert_equal "pmessage * __keyspace@${db}__:mystream xgroup-createconsumer" [$rd1 read]
  291. assert_equal "pmessage * __keyspace@${db}__:mystream xgroup-delconsumer" [$rd1 read]
  292. $rd1 close
  293. }
  294. test "Keyspace notifications: expired events (triggered expire)" {
  295. r config set notify-keyspace-events Ex
  296. r del foo
  297. set rd1 [redis_deferring_client]
  298. assert_equal {1} [psubscribe $rd1 *]
  299. r psetex foo 100 1
  300. wait_for_condition 50 100 {
  301. [r exists foo] == 0
  302. } else {
  303. fail "Key does not expire?!"
  304. }
  305. assert_equal "pmessage * __keyevent@${db}__:expired foo" [$rd1 read]
  306. $rd1 close
  307. }
  308. test "Keyspace notifications: expired events (background expire)" {
  309. r config set notify-keyspace-events Ex
  310. r del foo
  311. set rd1 [redis_deferring_client]
  312. assert_equal {1} [psubscribe $rd1 *]
  313. r psetex foo 100 1
  314. assert_equal "pmessage * __keyevent@${db}__:expired foo" [$rd1 read]
  315. $rd1 close
  316. }
  317. test "Keyspace notifications: evicted events" {
  318. r config set notify-keyspace-events Ee
  319. r config set maxmemory-policy allkeys-lru
  320. r flushdb
  321. set rd1 [redis_deferring_client]
  322. assert_equal {1} [psubscribe $rd1 *]
  323. r set foo bar
  324. r config set maxmemory 1
  325. assert_equal "pmessage * __keyevent@${db}__:evicted foo" [$rd1 read]
  326. r config set maxmemory 0
  327. $rd1 close
  328. r config set maxmemory-policy noeviction
  329. } {OK} {needs:config-maxmemory}
  330. test "Keyspace notifications: test CONFIG GET/SET of event flags" {
  331. r config set notify-keyspace-events gKE
  332. assert_equal {gKE} [lindex [r config get notify-keyspace-events] 1]
  333. r config set notify-keyspace-events {$lshzxeKE}
  334. assert_equal {$lshzxeKE} [lindex [r config get notify-keyspace-events] 1]
  335. r config set notify-keyspace-events KA
  336. assert_equal {AK} [lindex [r config get notify-keyspace-events] 1]
  337. r config set notify-keyspace-events EA
  338. assert_equal {AE} [lindex [r config get notify-keyspace-events] 1]
  339. }
  340. }