blockonkeys.tcl 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. set testmodule [file normalize tests/modules/blockonkeys.so]
  2. start_server {tags {"modules"}} {
  3. r module load $testmodule
  4. test "Module client blocked on keys: Circular BPOPPUSH" {
  5. set rd1 [redis_deferring_client]
  6. set rd2 [redis_deferring_client]
  7. r del src dst
  8. $rd1 fsl.bpoppush src dst 0
  9. $rd2 fsl.bpoppush dst src 0
  10. ;# wait until clients are actually blocked
  11. wait_for_condition 50 100 {
  12. [s 0 blocked_clients] eq {2}
  13. } else {
  14. fail "Clients are not blocked"
  15. }
  16. r fsl.push src 42
  17. assert_equal {42} [r fsl.getall src]
  18. assert_equal {} [r fsl.getall dst]
  19. }
  20. test "Module client blocked on keys: Self-referential BPOPPUSH" {
  21. set rd1 [redis_deferring_client]
  22. r del src
  23. $rd1 fsl.bpoppush src src 0
  24. ;# wait until clients are actually blocked
  25. wait_for_condition 50 100 {
  26. [s 0 blocked_clients] eq {1}
  27. } else {
  28. fail "Clients are not blocked"
  29. }
  30. r fsl.push src 42
  31. assert_equal {42} [r fsl.getall src]
  32. }
  33. test {Module client blocked on keys (no metadata): No block} {
  34. r del k
  35. r fsl.push k 33
  36. r fsl.push k 34
  37. r fsl.bpop k 0
  38. } {34}
  39. test {Module client blocked on keys (no metadata): Timeout} {
  40. r del k
  41. set rd [redis_deferring_client]
  42. $rd fsl.bpop k 1
  43. assert_equal {Request timedout} [$rd read]
  44. }
  45. test {Module client blocked on keys (no metadata): Blocked} {
  46. r del k
  47. set rd [redis_deferring_client]
  48. $rd fsl.bpop k 0
  49. ;# wait until clients are actually blocked
  50. wait_for_condition 50 100 {
  51. [s 0 blocked_clients] eq {1}
  52. } else {
  53. fail "Clients are not blocked"
  54. }
  55. r fsl.push k 34
  56. assert_equal {34} [$rd read]
  57. }
  58. test {Module client blocked on keys (with metadata): No block} {
  59. r del k
  60. r fsl.push k 34
  61. r fsl.bpopgt k 30 0
  62. } {34}
  63. test {Module client blocked on keys (with metadata): Timeout} {
  64. r del k
  65. set rd [redis_deferring_client]
  66. $rd client id
  67. set cid [$rd read]
  68. r fsl.push k 33
  69. $rd fsl.bpopgt k 35 1
  70. assert_equal {Request timedout} [$rd read]
  71. r client kill id $cid ;# try to smoke-out client-related memory leak
  72. }
  73. test {Module client blocked on keys (with metadata): Blocked, case 1} {
  74. r del k
  75. set rd [redis_deferring_client]
  76. $rd client id
  77. set cid [$rd read]
  78. r fsl.push k 33
  79. $rd fsl.bpopgt k 33 0
  80. ;# wait until clients are actually blocked
  81. wait_for_condition 50 100 {
  82. [s 0 blocked_clients] eq {1}
  83. } else {
  84. fail "Clients are not blocked"
  85. }
  86. r fsl.push k 34
  87. assert_equal {34} [$rd read]
  88. r client kill id $cid ;# try to smoke-out client-related memory leak
  89. }
  90. test {Module client blocked on keys (with metadata): Blocked, case 2} {
  91. r del k
  92. set rd [redis_deferring_client]
  93. $rd fsl.bpopgt k 35 0
  94. ;# wait until clients are actually blocked
  95. wait_for_condition 50 100 {
  96. [s 0 blocked_clients] eq {1}
  97. } else {
  98. fail "Clients are not blocked"
  99. }
  100. r fsl.push k 33
  101. r fsl.push k 34
  102. r fsl.push k 35
  103. r fsl.push k 36
  104. assert_equal {36} [$rd read]
  105. }
  106. test {Module client blocked on keys (with metadata): Blocked, CLIENT KILL} {
  107. r del k
  108. set rd [redis_deferring_client]
  109. $rd client id
  110. set cid [$rd read]
  111. $rd fsl.bpopgt k 35 0
  112. ;# wait until clients are actually blocked
  113. wait_for_condition 50 100 {
  114. [s 0 blocked_clients] eq {1}
  115. } else {
  116. fail "Clients are not blocked"
  117. }
  118. r client kill id $cid ;# try to smoke-out client-related memory leak
  119. }
  120. test {Module client blocked on keys (with metadata): Blocked, CLIENT UNBLOCK TIMEOUT} {
  121. r del k
  122. set rd [redis_deferring_client]
  123. $rd client id
  124. set cid [$rd read]
  125. $rd fsl.bpopgt k 35 0
  126. ;# wait until clients are actually blocked
  127. wait_for_condition 50 100 {
  128. [s 0 blocked_clients] eq {1}
  129. } else {
  130. fail "Clients are not blocked"
  131. }
  132. r client unblock $cid timeout ;# try to smoke-out client-related memory leak
  133. assert_equal {Request timedout} [$rd read]
  134. }
  135. test {Module client blocked on keys (with metadata): Blocked, CLIENT UNBLOCK ERROR} {
  136. r del k
  137. set rd [redis_deferring_client]
  138. $rd client id
  139. set cid [$rd read]
  140. $rd fsl.bpopgt k 35 0
  141. ;# wait until clients are actually blocked
  142. wait_for_condition 50 100 {
  143. [s 0 blocked_clients] eq {1}
  144. } else {
  145. fail "Clients are not blocked"
  146. }
  147. r client unblock $cid error ;# try to smoke-out client-related memory leak
  148. assert_error "*unblocked*" {$rd read}
  149. }
  150. test {Module client re-blocked on keys after woke up on wrong type} {
  151. r del k
  152. set rd [redis_deferring_client]
  153. $rd fsl.bpop k 0
  154. ;# wait until clients are actually blocked
  155. wait_for_condition 50 100 {
  156. [s 0 blocked_clients] eq {1}
  157. } else {
  158. fail "Clients are not blocked"
  159. }
  160. r lpush k 12
  161. r lpush k 13
  162. r lpush k 14
  163. r del k
  164. r fsl.push k 34
  165. assert_equal {34} [$rd read]
  166. assert_equal {1} [r get fsl_wrong_type] ;# first lpush caused one wrong-type wake-up
  167. }
  168. test {Module client blocked on keys woken up by LPUSH} {
  169. r del k
  170. set rd [redis_deferring_client]
  171. $rd blockonkeys.popall k
  172. # wait until client is actually blocked
  173. wait_for_condition 50 100 {
  174. [s 0 blocked_clients] eq {1}
  175. } else {
  176. fail "Client is not blocked"
  177. }
  178. r lpush k 42 squirrel banana
  179. assert_equal {banana squirrel 42} [$rd read]
  180. $rd close
  181. }
  182. test {Module client unblocks BLPOP} {
  183. r del k
  184. set rd [redis_deferring_client]
  185. $rd blpop k 3
  186. # wait until client is actually blocked
  187. wait_for_condition 50 100 {
  188. [s 0 blocked_clients] eq {1}
  189. } else {
  190. fail "Client is not blocked"
  191. }
  192. r blockonkeys.lpush k 42
  193. assert_equal {k 42} [$rd read]
  194. $rd close
  195. }
  196. test {Module unblocks module blocked on non-empty list} {
  197. r del k
  198. r lpush k aa
  199. # Module client blocks to pop 5 elements from list
  200. set rd [redis_deferring_client]
  201. $rd blockonkeys.blpopn k 5
  202. # Wait until client is actually blocked
  203. wait_for_condition 50 100 {
  204. [s 0 blocked_clients] eq {1}
  205. } else {
  206. fail "Client is not blocked"
  207. }
  208. # Check that RM_SignalKeyAsReady() can wake up BLPOPN
  209. r blockonkeys.lpush_unblock k bb cc ;# Not enough elements for BLPOPN
  210. r lpush k dd ee ff ;# Doesn't unblock module
  211. r blockonkeys.lpush_unblock k gg ;# Unblocks module
  212. assert_equal {gg ff ee dd cc} [$rd read]
  213. $rd close
  214. }
  215. }