redis-client 0.8.0 → 0.9.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: e7e7b7923ecb86353521db31036b3c5678683fcb6ed8ec5799c1ca6c6b5fcd44
4
- data.tar.gz: 9e782f9884b2f12eb0c58ca701da62e8945a14a1eca27c3052adbb0a1e4fe428
3
+ metadata.gz: 95dd96eda7210df59b85fafb8d2df5fa46cf0d3d2da10ad1ebf60137b8ec2652
4
+ data.tar.gz: d417951e19d9a20b7f96a2d4e520d433cd52c38209d8c46499ddfc0d6d4be941
5
5
  SHA512:
6
- metadata.gz: c77d09a8330bbcc4e8b2329a1ff9e660bb2c5ddf35cccafcf89f0b37ef9d89f579fa32b9ec7a7f64eecff12941ac835e4424dcf7ab9fdef12fc01ae73250959f
7
- data.tar.gz: 4c16639282ca539e04d07d363c28e663a5e409f6c6d9deef856158fe8d46a1e20669b44c025e978dc04965106148e1fd7fcd82cc1d50abc8c27fb4694b825e2e
6
+ metadata.gz: 0dd66a81c969a08abbb89140187e6a3a31aadcb258845082bf84bba792304ebc3d27852635fa4519805139eeecb7f405033b2b0c6acc4d39f7823873cd91dbdc
7
+ data.tar.gz: 4a9f5b79ffc8d195a3fac2cd439750d43124bb78583eef840564262d25565b2e585d8d77eb3f9d2096ec938fa4db7fe7a775c5ba5f80c4e2bd91f2b121901a98
data/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # Unreleased
2
2
 
3
+ # 0.9.0
4
+
5
+ - Automatically reconnect if the process was forked.
6
+
7
+ # 0.8.1
8
+
9
+ - Make the client resilient to `Timeout.timeout` or `Thread#kill` use (it still is very much discouraged to use either).
10
+ Use of async interrupts could cause responses to be interleaved.
11
+ - hiredis: handle commands returning a top-level `false` (no command does this today, but some extensions might).
12
+ - Workaround a bug in Ruby 2.6 causing a crash if the `debug` gem is enabled when `redis-client` is being required. Fix: #48
13
+
3
14
  # 0.8.0
4
15
 
5
16
  - Add a `connect` interface to the instrumentation API.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- redis-client (0.8.0)
4
+ redis-client (0.9.0)
5
5
  connection_pool
6
6
 
7
7
  GEM
@@ -10,7 +10,7 @@ GEM
10
10
  ast (2.4.2)
11
11
  benchmark-ips (2.10.0)
12
12
  byebug (11.1.3)
13
- connection_pool (2.2.5)
13
+ connection_pool (2.3.0)
14
14
  hiredis (0.6.3)
15
15
  hiredis (0.6.3-java)
16
16
  minitest (5.15.0)
data/README.md CHANGED
@@ -437,15 +437,6 @@ Contrary to the `redis` gem, `redis-client` doesn't protect against concurrent a
437
437
  To use `redis-client` in concurrent environments, you MUST use a connection pool, or
438
438
  have one client per Thread or Fiber.
439
439
 
440
- ### Fork Safety
441
-
442
- `redis-client` doesn't try to detect forked processes. You MUST disconnect all clients before forking your process.
443
-
444
- ```ruby
445
- redis.close
446
- Process.fork ...
447
- ```
448
-
449
440
  ## Development
450
441
 
451
442
  After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -12,7 +12,7 @@ class RedisClient
12
12
  DEFAULT_DB = 0
13
13
 
14
14
  module Common
15
- attr_reader :db, :password, :id, :ssl, :ssl_params, :command_builder,
15
+ attr_reader :db, :password, :id, :ssl, :ssl_params, :command_builder, :inherit_socket,
16
16
  :connect_timeout, :read_timeout, :write_timeout, :driver, :connection_prelude, :protocol
17
17
 
18
18
  alias_method :ssl?, :ssl
@@ -32,6 +32,7 @@ class RedisClient
32
32
  protocol: 3,
33
33
  client_implementation: RedisClient,
34
34
  command_builder: CommandBuilder,
35
+ inherit_socket: false,
35
36
  reconnect_attempts: false
36
37
  )
37
38
  @username = username
@@ -54,6 +55,7 @@ class RedisClient
54
55
  end
55
56
 
56
57
  @command_builder = command_builder
58
+ @inherit_socket = inherit_socket
57
59
 
58
60
  reconnect_attempts = Array.new(reconnect_attempts, 0).freeze if reconnect_attempts.is_a?(Integer)
59
61
  @reconnect_attempts = reconnect_attempts
@@ -2,9 +2,21 @@
2
2
 
3
3
  class RedisClient
4
4
  module ConnectionMixin
5
+ def initialize
6
+ @pending_reads = 0
7
+ end
8
+
9
+ def revalidate
10
+ if @pending_reads == 0 && connected?
11
+ self
12
+ end
13
+ end
14
+
5
15
  def call(command, timeout)
16
+ @pending_reads += 1
6
17
  write(command)
7
18
  result = read(timeout)
19
+ @pending_reads -= 1
8
20
  if result.is_a?(CommandError)
9
21
  result._set_command(command)
10
22
  raise result
@@ -18,11 +30,13 @@ class RedisClient
18
30
 
19
31
  size = commands.size
20
32
  results = Array.new(commands.size)
33
+ @pending_reads += size
21
34
  write_multi(commands)
22
35
 
23
36
  size.times do |index|
24
37
  timeout = timeouts && timeouts[index]
25
38
  result = read(timeout)
39
+ @pending_reads -= 1
26
40
  if result.is_a?(CommandError)
27
41
  result._set_command(commands[index])
28
42
  exception ||= result
@@ -51,46 +51,26 @@ class RedisClient
51
51
 
52
52
  methods = %w(pipelined multi pubsub call call_v call_once call_once_v blocking_call blocking_call_v)
53
53
  iterable_methods = %w(scan sscan hscan zscan)
54
- begin
55
- methods.each do |method|
56
- class_eval <<~RUBY, __FILE__, __LINE__ + 1
57
- def #{method}(...)
58
- with { |r| r.#{method}(...) }
59
- end
60
- RUBY
61
- end
62
-
63
- iterable_methods.each do |method|
64
- class_eval <<~RUBY, __FILE__, __LINE__ + 1
65
- def #{method}(...)
66
- unless block_given?
67
- return to_enum(__callee__, ...)
68
- end
54
+ methods.each do |method|
55
+ class_eval <<~RUBY, __FILE__, __LINE__ + 1
56
+ def #{method}(*args, &block)
57
+ with { |r| r.#{method}(*args, &block) }
58
+ end
59
+ ruby2_keywords :#{method} if respond_to?(:ruby2_keywords, true)
60
+ RUBY
61
+ end
69
62
 
70
- with { |r| r.#{method}(...) }
71
- end
72
- RUBY
73
- end
74
- rescue SyntaxError
75
- methods.each do |method|
76
- class_eval <<~RUBY, __FILE__, __LINE__ + 1
77
- def #{method}(*args, &block)
78
- with { |r| r.#{method}(*args, &block) }
63
+ iterable_methods.each do |method|
64
+ class_eval <<~RUBY, __FILE__, __LINE__ + 1
65
+ def #{method}(*args, &block)
66
+ unless block_given?
67
+ return to_enum(__callee__, *args)
79
68
  end
80
- RUBY
81
- end
82
-
83
- iterable_methods.each do |method|
84
- class_eval <<~RUBY, __FILE__, __LINE__ + 1
85
- def #{method}(*args, &block)
86
- unless block_given?
87
- return to_enum(__callee__, *args)
88
- end
89
69
 
90
- with { |r| r.#{method}(*args, &block) }
91
- end
92
- RUBY
93
- end
70
+ with { |r| r.#{method}(*args, &block) }
71
+ end
72
+ ruby2_keywords :#{method} if respond_to?(:ruby2_keywords, true)
73
+ RUBY
94
74
  end
95
75
 
96
76
  private
@@ -41,6 +41,7 @@ class RedisClient
41
41
  SUPPORTS_RESOLV_TIMEOUT = Socket.method(:tcp).parameters.any? { |p| p.last == :resolv_timeout }
42
42
 
43
43
  def initialize(config, connect_timeout:, read_timeout:, write_timeout:)
44
+ super()
44
45
  socket = if config.path
45
46
  UNIXSocket.new(config.path)
46
47
  else
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class RedisClient
4
- VERSION = "0.8.0"
4
+ VERSION = "0.9.0"
5
5
  end
data/lib/redis_client.rb CHANGED
@@ -67,6 +67,7 @@ class RedisClient
67
67
  @read_timeout = read_timeout
68
68
  @write_timeout = write_timeout
69
69
  @command_builder = config.command_builder
70
+ @pid = Process.pid
70
71
  end
71
72
 
72
73
  def timeout=(timeout)
@@ -416,7 +417,7 @@ class RedisClient
416
417
  end
417
418
 
418
419
  def close
419
- raw_connection&.close
420
+ @raw_connection&.close
420
421
  @raw_connection = nil
421
422
  self
422
423
  end
@@ -597,6 +598,8 @@ class RedisClient
597
598
  end
598
599
 
599
600
  def ensure_connected(retryable: true)
601
+ close if !config.inherit_socket && @pid != Process.pid
602
+
600
603
  if @disable_reconnection
601
604
  if block_given?
602
605
  yield @raw_connection
@@ -614,7 +617,6 @@ class RedisClient
614
617
  connection
615
618
  end
616
619
  rescue ConnectionError, ProtocolError => error
617
- connection&.close
618
620
  close
619
621
 
620
622
  if !@disable_reconnection && config.retry_connecting?(tries, error)
@@ -631,7 +633,6 @@ class RedisClient
631
633
  @disable_reconnection = true
632
634
  yield connection
633
635
  rescue ConnectionError, ProtocolError
634
- connection&.close
635
636
  close
636
637
  raise
637
638
  ensure
@@ -641,10 +642,13 @@ class RedisClient
641
642
  end
642
643
 
643
644
  def raw_connection
645
+ @raw_connection = @raw_connection&.revalidate
644
646
  @raw_connection ||= connect
645
647
  end
646
648
 
647
649
  def connect
650
+ @pid = Process.pid
651
+
648
652
  connection = Middlewares.connect(config) do
649
653
  config.driver.new(
650
654
  config,
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.8.0
4
+ version: 0.9.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-07 00:00:00.000000000 Z
11
+ date: 2022-09-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: connection_pool