diff --git a/lib/redis_client/cluster/router.rb b/lib/redis_client/cluster/router.rb index a73e90b6..45fd13c3 100644 --- a/lib/redis_client/cluster/router.rb +++ b/lib/redis_client/cluster/router.rb @@ -8,6 +8,8 @@ require 'redis_client/cluster/node' require 'redis_client/cluster/node_key' require 'redis_client/cluster/normalized_cmd_name' +require 'redis_client/cluster/transaction' +require 'redis_client/cluster/optimistic_locking' class RedisClient class Cluster @@ -44,6 +46,7 @@ def send_command(method, command, *args, &block) # rubocop:disable Metrics/AbcSi when 'memory' then send_memory_command(method, command, args, &block) when 'script' then send_script_command(method, command, args, &block) when 'pubsub' then send_pubsub_command(method, command, args, &block) + when 'watch' then send_watch_command(command, &block) when 'acl', 'auth', 'bgrewriteaof', 'bgsave', 'quit', 'save' @node.call_all(method, command, args).first.then(&TSF.call(block)) when 'flushall', 'flushdb' @@ -308,6 +311,17 @@ def send_pubsub_command(method, command, args, &block) # rubocop:disable Metrics end end + # for redis-rb + def send_watch_command(command) + ::RedisClient::Cluster::OptimisticLocking.new(self).watch(command[1..]) do |c, slot| + transaction = ::RedisClient::Cluster::Transaction.new( + self, @command_builder, node: c, slot: slot + ) + yield transaction + transaction.execute + end + end + def update_cluster_info! @node.reload! end diff --git a/test/redis_client/test_cluster.rb b/test/redis_client/test_cluster.rb index 6b1a580c..84b77cac 100644 --- a/test/redis_client/test_cluster.rb +++ b/test/redis_client/test_cluster.rb @@ -363,6 +363,21 @@ def test_transaction_in_race_condition assert_equal(%w[3 4], @client.call('MGET', '{key}1', '{key}2')) end + # for redis-rb + def test_transaction_with_standalone_watch_command + @client.call('MSET', '{key}1', '0', '{key}2', '0') + + got = @client.call('WATCH', '{key}1', '{key}2') do |tx| + tx.call('ECHO', 'START') + tx.call('SET', '{key}1', '1') + tx.call('SET', '{key}2', '2') + tx.call('ECHO', 'FINISH') + end + + assert_equal(%w[START OK OK FINISH], got) + assert_equal(%w[1 2], @client.call('MGET', '{key}1', '{key}2')) + end + def test_pubsub_without_subscription pubsub = @client.pubsub assert_nil(pubsub.next_event(0.01))