Open hugopl opened 2 years ago
I didn't fully test this yet, but the monkey patch I'll need to use will be something like this:
class Redis
def multi : Redis::TransactionApi
@strategy = strategy = Redis::Strategy::Transaction.new(connection)
strategy.begin
Redis::TransactionApi.new(strategy, @namespace.to_s)
rescue ex : Redis::ConnectionError | Redis::CommandTimeoutError
close
raise ex
end
def exec
strategy = @strategy.as?(Redis::Strategy::Transaction)
raise Redis::Error.new("Not in a multi call") if strategy.nil?
strategy.commit.as(Array(RedisValue))
rescue ex : Redis::ConnectionError | Redis::CommandTimeoutError
close
raise ex
ensure
connection = @connection
@strategy = Redis::Strategy::SingleStatement.new(connection) if connection
end
end
BTW I'm using this monkey patch in production for a year now.
# 🐒️ patch to allow use of MULTI commands without a block
#
# An upstream issue was filed at: https://github.com/stefanwille/crystal-redis/issues/129
class Redis
def multi : Redis::TransactionApi
raise Redis::Error.new("Nested transaction") if @strategy.is_a?(Redis::Strategy::Transaction)
@strategy = strategy = Redis::Strategy::Transaction.new(connection)
strategy.begin
Redis::TransactionApi.new(strategy, @namespace.to_s)
rescue ex : Redis::ConnectionError | Redis::CommandTimeoutError
close
raise ex
end
def exec
strategy = @strategy.as?(Redis::Strategy::Transaction)
raise Redis::Error.new("Not in a multi call") if strategy.nil?
strategy.commit.as(Array(RedisValue))
rescue ex : Redis::ConnectionError | Redis::CommandTimeoutError
close
raise ex
ensure
connection = @connection
@strategy = Redis::Strategy::SingleStatement.new(connection) if connection
end
end
Hi,
I need to start transaction for more than one redis server and write the same set of keys for all them in this transaction. With current
multi
this isn't possible since it requires a block. But I can't just call:Since the
write_keys
procedure is slow and memory hungry. The solution is to just send theMULTI
/EXEC
command myself, but I was thinking if a patch to allow a non-blocking version ofmulti
would be acceptable.The only implementation issue I foresee is how to restore the
Redis::Strategy::SingleStatement
to theRedis
object without make everything coupled.... another option would be to not change the@strategy
when using non-blockingmulti
...I can create a patch for this once is decided what is acceptable and what isn't, so I don't waste my time nether time of others :wink: .