# Test PUBSUB shard propagation in a cluster slot. source tests/support/cluster.tcl # Start a cluster with 3 masters and 3 replicas. start_cluster 3 3 {tags {external:skip cluster}} { set cluster [valkey_cluster 127.0.0.1:[srv 0 port]] test "Pub/Sub shard basics" { set slot [$cluster cluster keyslot "channel.0"] array set publishnode [$cluster masternode_for_slot $slot] array set notshardnode [$cluster masternode_notfor_slot $slot] set publishclient [valkey_client_by_addr $publishnode(host) $publishnode(port)] set subscribeclient [valkey_deferring_client_by_addr $publishnode(host) $publishnode(port)] set subscribeclient2 [valkey_deferring_client_by_addr $publishnode(host) $publishnode(port)] set anotherclient [valkey_deferring_client_by_addr $notshardnode(host) $notshardnode(port)] $subscribeclient ssubscribe channel.0 $subscribeclient read $subscribeclient2 ssubscribe channel.0 $subscribeclient2 read $anotherclient ssubscribe channel.0 catch {$anotherclient read} err assert_match {MOVED *} $err set data [randomValue] $publishclient spublish channel.0 $data set msg [$subscribeclient read] assert_equal $data [lindex $msg 2] set msg [$subscribeclient2 read] assert_equal $data [lindex $msg 2] $publishclient close $subscribeclient close $subscribeclient2 close $anotherclient close } test "client can't subscribe to multiple shard channels across different slots in same call" { catch {$cluster ssubscribe channel.0 channel.1} err assert_match {CROSSSLOT Keys*} $err } test "client can subscribe to multiple shard channels across different slots in separate call" { $cluster ssubscribe ch3 $cluster ssubscribe ch7 $cluster sunsubscribe ch3 $cluster sunsubscribe ch7 } test "sunsubscribe without specifying any channel would unsubscribe all shard channels subscribed" { set publishclient [valkey_client_by_addr $publishnode(host) $publishnode(port)] set subscribeclient [valkey_deferring_client_by_addr $publishnode(host) $publishnode(port)] set sub_res [ssubscribe $subscribeclient [list "\{channel.0\}1" "\{channel.0\}2" "\{channel.0\}3"]] assert_equal [list 1 2 3] $sub_res sunsubscribe $subscribeclient # wait for the unsubscribe to take effect wait_for_condition 50 10 { [$publishclient spublish "\{channel.0\}1" hello] eq 0 } else { fail "unsubscribe did not take effect as expected" } assert_equal 0 [$publishclient spublish "\{channel.0\}1" hello] assert_equal 0 [$publishclient spublish "\{channel.0\}2" hello] assert_equal 0 [$publishclient spublish "\{channel.0\}3" hello] $publishclient close $subscribeclient close } test "Verify Pub/Sub and Pub/Sub shard no overlap" { set slot [$cluster cluster keyslot "channel.0"] array set publishnode [$cluster masternode_for_slot $slot] array set notshardnode [$cluster masternode_notfor_slot $slot] set publishshardclient [valkey_client_by_addr $publishnode(host) $publishnode(port)] set publishclient [valkey_deferring_client_by_addr $publishnode(host) $publishnode(port)] set subscribeshardclient [valkey_deferring_client_by_addr $publishnode(host) $publishnode(port)] set subscribeclient [valkey_deferring_client_by_addr $publishnode(host) $publishnode(port)] $subscribeshardclient deferred 1 $subscribeshardclient ssubscribe channel.0 $subscribeshardclient read $subscribeclient deferred 1 $subscribeclient subscribe channel.0 $subscribeclient read set sharddata "testingpubsubdata" $publishshardclient spublish channel.0 $sharddata set data "somemoredata" $publishclient publish channel.0 $data set msg [$subscribeshardclient read] assert_equal $sharddata [lindex $msg 2] set msg [$subscribeclient read] assert_equal $data [lindex $msg 2] $cluster close $publishclient close $subscribeclient close $subscribeshardclient close } test "PUBSUB channels/shardchannels" { set subscribeclient [valkey_deferring_client_by_addr $publishnode(host) $publishnode(port)] set subscribeclient2 [valkey_deferring_client_by_addr $publishnode(host) $publishnode(port)] set subscribeclient3 [valkey_deferring_client_by_addr $publishnode(host) $publishnode(port)] set publishclient [valkey_client_by_addr $publishnode(host) $publishnode(port)] ssubscribe $subscribeclient [list "\{channel.0\}1"] ssubscribe $subscribeclient2 [list "\{channel.0\}2"] ssubscribe $subscribeclient3 [list "\{channel.0\}3"] assert_equal {3} [llength [$publishclient pubsub shardchannels]] subscribe $subscribeclient [list "\{channel.0\}4"] assert_equal {3} [llength [$publishclient pubsub shardchannels]] sunsubscribe $subscribeclient $subscribeclient read set channel_list [$publishclient pubsub shardchannels] assert_equal {2} [llength $channel_list] assert {[lsearch -exact $channel_list "\{channel.0\}2"] >= 0} assert {[lsearch -exact $channel_list "\{channel.0\}3"] >= 0} } } ;# start_cluster