redis-client 0.9.0 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 95dd96eda7210df59b85fafb8d2df5fa46cf0d3d2da10ad1ebf60137b8ec2652
4
- data.tar.gz: d417951e19d9a20b7f96a2d4e520d433cd52c38209d8c46499ddfc0d6d4be941
3
+ metadata.gz: 27142ef61a44133a72e2a087afc39986ebcfe5fae30a7ee5f6eb3f702ef35ad2
4
+ data.tar.gz: f078880a52dec2f62d3b68188cfea8108ec433742f2f7e697def7a7bece332ac
5
5
  SHA512:
6
- metadata.gz: 0dd66a81c969a08abbb89140187e6a3a31aadcb258845082bf84bba792304ebc3d27852635fa4519805139eeecb7f405033b2b0c6acc4d39f7823873cd91dbdc
7
- data.tar.gz: 4a9f5b79ffc8d195a3fac2cd439750d43124bb78583eef840564262d25565b2e585d8d77eb3f9d2096ec938fa4db7fe7a775c5ba5f80c4e2bd91f2b121901a98
6
+ metadata.gz: 76c7b23cb0ba419fdb9505e5cd4eb58c1c6d38d2e2fcd82778429b346dfa02a94ce4a9077c28252d8c71d1667cc45270bfc0790190e42b0d37341493bbb105f5
7
+ data.tar.gz: 071ec50fabaa72512101d0f408154e432e5f9950927607d8d6bcf8c7f3d5d4c9f49f40de3a24aa6957019751a598b70ae9db525002c03d7beb05312fc082e053
data/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Unreleased
2
2
 
3
+ # 0.10.0
4
+
5
+ - Added instance scoped middlewares. See: #53
6
+ - Allow subclasses of accepted types as command arguments. Fix: #51
7
+ - Improve hiredis driver error messages.
8
+
3
9
  # 0.9.0
4
10
 
5
11
  - Automatically reconnect if the process was forked.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- redis-client (0.9.0)
4
+ redis-client (0.10.0)
5
5
  connection_pool
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -343,12 +343,13 @@ end
343
343
 
344
344
  ## Production
345
345
 
346
- ### Instrumentation
346
+ ### Instrumentation and Middlewares
347
347
 
348
- `redis-client` offers a public instrumentation API monitoring tools.
348
+ `redis-client` offers a public middleware API to aid in monitoring and library extension. Middleware can be registered
349
+ either globally or on a given configuration instance.
349
350
 
350
351
  ```ruby
351
- module MyRedisInstrumentation
352
+ module MyGlobalRedisInstrumentation
352
353
  def connect(redis_config)
353
354
  MyMonitoringService.instrument("redis.connect") { super }
354
355
  end
@@ -361,10 +362,17 @@ module MyRedisInstrumentation
361
362
  MyMonitoringService.instrument("redis.pipeline") { super }
362
363
  end
363
364
  end
364
- RedisClient.register(MyRedisInstrumentation)
365
+ RedisClient.register(MyGlobalRedisInstrumentation)
365
366
  ```
366
367
 
367
- Note that this instrumentation is global.
368
+ Note that `RedisClient.register` is global and apply to all `RedisClient` instances.
369
+
370
+ To add middlewares to only a single client, you can provide them when creating the config:
371
+
372
+ ```ruby
373
+ redis_config = RedisClient.config(middlewares: [AnotherRedisInstrumentation])
374
+ redis_config.new_client
375
+ ```
368
376
 
369
377
  ### Timeouts
370
378
 
data/Rakefile CHANGED
@@ -67,12 +67,15 @@ namespace :hiredis do
67
67
  end
68
68
  end
69
69
 
70
+ benchmark_suites = %w(single pipelined)
71
+ benchmark_modes = %i[ruby yjit hiredis]
70
72
  namespace :benchmark do
71
- task :record do
72
- system("rm -rf tmp/*.benchmark")
73
- %w(single pipelined).each do |suite|
74
- %i[ruby yjit hiredis].each do |mode|
75
- output_path = "benchmark/#{suite}_#{mode}.md"
73
+ benchmark_suites.each do |suite|
74
+ benchmark_modes.each do |mode|
75
+ name = "#{suite}_#{mode}"
76
+ task name do
77
+ output_path = "benchmark/#{name}.md"
78
+ sh "rm", "-f", output_path
76
79
  File.open(output_path, "w+") do |output|
77
80
  output.puts("ruby: `#{RUBY_DESCRIPTION}`\n\n")
78
81
  output.puts("redis-server: `#{`redis-server -v`.strip}`\n\n")
@@ -103,6 +106,8 @@ namespace :benchmark do
103
106
  end
104
107
  end
105
108
  end
109
+
110
+ task all: benchmark_suites.flat_map { |s| benchmark_modes.flat_map { |m| "#{s}_#{m}" } }
106
111
  end
107
112
 
108
113
  if hiredis_supported
@@ -13,7 +13,8 @@ class RedisClient
13
13
 
14
14
  module Common
15
15
  attr_reader :db, :password, :id, :ssl, :ssl_params, :command_builder, :inherit_socket,
16
- :connect_timeout, :read_timeout, :write_timeout, :driver, :connection_prelude, :protocol
16
+ :connect_timeout, :read_timeout, :write_timeout, :driver, :connection_prelude, :protocol,
17
+ :middlewares_stack
17
18
 
18
19
  alias_method :ssl?, :ssl
19
20
 
@@ -33,7 +34,8 @@ class RedisClient
33
34
  client_implementation: RedisClient,
34
35
  command_builder: CommandBuilder,
35
36
  inherit_socket: false,
36
- reconnect_attempts: false
37
+ reconnect_attempts: false,
38
+ middlewares: false
37
39
  )
38
40
  @username = username
39
41
  @password = password
@@ -60,6 +62,15 @@ class RedisClient
60
62
  reconnect_attempts = Array.new(reconnect_attempts, 0).freeze if reconnect_attempts.is_a?(Integer)
61
63
  @reconnect_attempts = reconnect_attempts
62
64
  @connection_prelude = build_connection_prelude
65
+
66
+ middlewares_stack = Middlewares
67
+ if middlewares && !middlewares.empty?
68
+ middlewares_stack = Class.new(Middlewares)
69
+ middlewares.each do |mod|
70
+ middlewares_stack.include(mod)
71
+ end
72
+ end
73
+ @middlewares_stack = middlewares_stack
63
74
  end
64
75
 
65
76
  def username
@@ -1,8 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class RedisClient
4
- module Middlewares
5
- extend self
4
+ class BasicMiddleware
5
+ attr_reader :client
6
+
7
+ def initialize(client)
8
+ @client = client
9
+ end
6
10
 
7
11
  def connect(_config)
8
12
  yield
@@ -13,4 +17,7 @@ class RedisClient
13
17
  end
14
18
  alias_method :call_pipelined, :call
15
19
  end
20
+
21
+ class Middlewares < BasicMiddleware
22
+ end
16
23
  end
@@ -10,12 +10,12 @@ class RedisClient
10
10
 
11
11
  EOL = "\r\n".b.freeze
12
12
  EOL_SIZE = EOL.bytesize
13
- DUMP_TYPES = {
13
+ DUMP_TYPES = { # rubocop:disable Style/MutableConstant
14
14
  String => :dump_string,
15
15
  Symbol => :dump_symbol,
16
16
  Integer => :dump_numeric,
17
17
  Float => :dump_numeric,
18
- }.freeze
18
+ }
19
19
  PARSER_TYPES = {
20
20
  '#' => :parse_boolean,
21
21
  '$' => :parse_blob,
@@ -55,8 +55,12 @@ class RedisClient
55
55
  end
56
56
 
57
57
  def dump_any(object, buffer)
58
- method = DUMP_TYPES.fetch(object.class) do
59
- raise TypeError, "Unsupported command argument type: #{object.class}"
58
+ method = DUMP_TYPES.fetch(object.class) do |unexpected_class|
59
+ if superclass = DUMP_TYPES.keys.find { |t| t > unexpected_class }
60
+ DUMP_TYPES[unexpected_class] = DUMP_TYPES[superclass]
61
+ else
62
+ raise TypeError, "Unsupported command argument type: #{unexpected_class}"
63
+ end
60
64
  end
61
65
  send(method, object, buffer)
62
66
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class RedisClient
4
- VERSION = "0.9.0"
4
+ VERSION = "0.10.0"
5
5
  end
data/lib/redis_client.rb CHANGED
@@ -145,7 +145,7 @@ class RedisClient
145
145
  end
146
146
 
147
147
  def register(middleware)
148
- Middlewares.extend(middleware)
148
+ Middlewares.include(middleware)
149
149
  end
150
150
  end
151
151
 
@@ -153,6 +153,7 @@ class RedisClient
153
153
 
154
154
  def initialize(config, **)
155
155
  super
156
+ @middlewares = config.middlewares_stack.new(self)
156
157
  @raw_connection = nil
157
158
  @disable_reconnection = false
158
159
  end
@@ -195,7 +196,7 @@ class RedisClient
195
196
  def call(*command, **kwargs)
196
197
  command = @command_builder.generate(command, kwargs)
197
198
  result = ensure_connected do |connection|
198
- Middlewares.call(command, config) do
199
+ @middlewares.call(command, config) do
199
200
  connection.call(command, nil)
200
201
  end
201
202
  end
@@ -210,7 +211,7 @@ class RedisClient
210
211
  def call_v(command)
211
212
  command = @command_builder.generate(command)
212
213
  result = ensure_connected do |connection|
213
- Middlewares.call(command, config) do
214
+ @middlewares.call(command, config) do
214
215
  connection.call(command, nil)
215
216
  end
216
217
  end
@@ -225,7 +226,7 @@ class RedisClient
225
226
  def call_once(*command, **kwargs)
226
227
  command = @command_builder.generate(command, kwargs)
227
228
  result = ensure_connected(retryable: false) do |connection|
228
- Middlewares.call(command, config) do
229
+ @middlewares.call(command, config) do
229
230
  connection.call(command, nil)
230
231
  end
231
232
  end
@@ -240,7 +241,7 @@ class RedisClient
240
241
  def call_once_v(command)
241
242
  command = @command_builder.generate(command)
242
243
  result = ensure_connected(retryable: false) do |connection|
243
- Middlewares.call(command, config) do
244
+ @middlewares.call(command, config) do
244
245
  connection.call(command, nil)
245
246
  end
246
247
  end
@@ -256,7 +257,7 @@ class RedisClient
256
257
  command = @command_builder.generate(command, kwargs)
257
258
  error = nil
258
259
  result = ensure_connected do |connection|
259
- Middlewares.call(command, config) do
260
+ @middlewares.call(command, config) do
260
261
  connection.call(command, timeout)
261
262
  end
262
263
  rescue ReadTimeoutError => error
@@ -276,7 +277,7 @@ class RedisClient
276
277
  command = @command_builder.generate(command)
277
278
  error = nil
278
279
  result = ensure_connected do |connection|
279
- Middlewares.call(command, config) do
280
+ @middlewares.call(command, config) do
280
281
  connection.call(command, timeout)
281
282
  end
282
283
  rescue ReadTimeoutError => error
@@ -347,7 +348,7 @@ class RedisClient
347
348
  else
348
349
  results = ensure_connected(retryable: pipeline._retryable?) do |connection|
349
350
  commands = pipeline._commands
350
- Middlewares.call_pipelined(commands, config) do
351
+ @middlewares.call_pipelined(commands, config) do
351
352
  connection.call_pipelined(commands, pipeline._timeouts)
352
353
  end
353
354
  end
@@ -367,7 +368,7 @@ class RedisClient
367
368
  begin
368
369
  if transaction = build_transaction(&block)
369
370
  commands = transaction._commands
370
- results = Middlewares.call_pipelined(commands, config) do
371
+ results = @middlewares.call_pipelined(commands, config) do
371
372
  connection.call_pipelined(commands, nil)
372
373
  end.last
373
374
  else
@@ -386,7 +387,7 @@ class RedisClient
386
387
  else
387
388
  ensure_connected(retryable: transaction._retryable?) do |connection|
388
389
  commands = transaction._commands
389
- Middlewares.call_pipelined(commands, config) do
390
+ @middlewares.call_pipelined(commands, config) do
390
391
  connection.call_pipelined(commands, nil)
391
392
  end.last
392
393
  end
@@ -649,7 +650,7 @@ class RedisClient
649
650
  def connect
650
651
  @pid = Process.pid
651
652
 
652
- connection = Middlewares.connect(config) do
653
+ connection = @middlewares.connect(config) do
653
654
  config.driver.new(
654
655
  config,
655
656
  connect_timeout: connect_timeout,
@@ -667,13 +668,13 @@ class RedisClient
667
668
  # The connection prelude is deliberately not sent to Middlewares
668
669
  if config.sentinel?
669
670
  prelude << ["ROLE"]
670
- role, = Middlewares.call_pipelined(prelude, config) do
671
+ role, = @middlewares.call_pipelined(prelude, config) do
671
672
  connection.call_pipelined(prelude, nil).last
672
673
  end
673
674
  config.check_role!(role)
674
675
  else
675
676
  unless prelude.empty?
676
- Middlewares.call_pipelined(prelude, config) do
677
+ @middlewares.call_pipelined(prelude, config) do
677
678
  connection.call_pipelined(prelude, nil)
678
679
  end
679
680
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redis-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jean Boussier
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-09-22 00:00:00.000000000 Z
11
+ date: 2022-10-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: connection_pool