diff --git a/lib/3scale/backend/async_redis/protocol/extended_resp2.rb b/lib/3scale/backend/async_redis/protocol/extended_resp2.rb new file mode 100644 index 00000000..2e8a8031 --- /dev/null +++ b/lib/3scale/backend/async_redis/protocol/extended_resp2.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +require 'async/redis/protocol/resp2' + +module ThreeScale + module Backend + module AsyncRedis + module Protocol + + # Custom Redis Protocol supporting Redis logical DBs + class ExtendedRESP2 + def initialize(db: nil) + @db = db + end + + def client(stream) + client = Async::Redis::Protocol::RESP2.client(stream) + + if @db + client.write_request(["SELECT", @db]) + client.read_response + end + + client + end + end + end + end + end +end diff --git a/lib/3scale/backend/storage_async/client.rb b/lib/3scale/backend/storage_async/client.rb index 29ecf0cc..c989e72a 100644 --- a/lib/3scale/backend/storage_async/client.rb +++ b/lib/3scale/backend/storage_async/client.rb @@ -1,6 +1,7 @@ require 'async/io' require 'async/redis/client' require 'async/redis/sentinels' +require '3scale/backend/async_redis/protocol/extended_resp2' module ThreeScale module Backend @@ -71,20 +72,34 @@ def initialize_client(opts) end def init_host_client(opts) - uri = URI(opts[:url] || '') - host = uri.host || DEFAULT_HOST - port = uri.port || DEFAULT_PORT - - endpoint = Async::IO::Endpoint.tcp(host, port) - Async::Redis::Client.new(endpoint, limit: opts[:max_connections]) + endpoint = make_redis_endpoint(opts) + protocol = make_redis_protocol(opts) + Async::Redis::Client.new(endpoint, protocol: protocol, limit: opts[:max_connections]) end def init_sentinels_client(opts) uri = URI(opts[:url] || '') name = uri.host role = opts[:role] || :master + protocol = make_redis_protocol(opts) + + Async::Redis::SentinelsClient.new(name, opts[:sentinels], role, protocol) + end + + # RESP2 with support for logical DBs + def make_redis_protocol(opts) + uri = URI(opts[:url] || "") + db = uri.path[1..-1] + + ThreeScale::Backend::AsyncRedis::Protocol::ExtendedRESP2.new(db: db) + end + + def make_redis_endpoint(opts) + uri = URI(opts[:url] || "") + host = uri.host || DEFAULT_HOST + port = uri.port || DEFAULT_PORT - Async::Redis::SentinelsClient.new(name, opts[:sentinels], role) + Async::IO::Endpoint.tcp(host, port) end end end