dalli 4.3.0 → 4.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +34 -0
- data/Gemfile +4 -0
- data/lib/dalli/client.rb +5 -3
- data/lib/dalli/instrumentation.rb +3 -13
- data/lib/dalli/key_manager.rb +1 -1
- data/lib/dalli/pipelined_getter.rb +2 -2
- data/lib/dalli/pipelined_setter.rb +1 -1
- data/lib/dalli/protocol/connection_manager.rb +1 -1
- data/lib/dalli/socket.rb +17 -8
- data/lib/dalli/version.rb +1 -1
- data/lib/dalli.rb +3 -0
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c21c31c46fc4381658892703d01baf8611392f5c1f72b9473013d2e53bc23254
|
|
4
|
+
data.tar.gz: 1fd1a3ea06cc4bab1ebc1192e62ede8318521e7867a84b3dd09096364560979f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9c79888857cb9c9edc9a1f86447e630b54f52040305806ffe92d0966d326e78607e06387c6bbbcac8b96b380737389da2bcf98a9f93ef91e487e2a2152e7aad7
|
|
7
|
+
data.tar.gz: f1783996f1d49db8985b755e78c3df6cee25776504504aa1ce303d665fc4798d3b09b8136d97e23dc2a3de8243bca68e7db2e00dbd2942c05e2f918d8efd8d1a
|
data/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,40 @@
|
|
|
1
1
|
Dalli Changelog
|
|
2
2
|
=====================
|
|
3
3
|
|
|
4
|
+
4.3.1
|
|
5
|
+
==========
|
|
6
|
+
|
|
7
|
+
Bug Fixes:
|
|
8
|
+
|
|
9
|
+
- Fix socket compatibility with gems that monkey-patch TCPSocket (#996, #1012)
|
|
10
|
+
- Gems like `socksify` and `resolv-replace` modify `TCPSocket#initialize`, breaking Ruby 3.0+'s `connect_timeout:` keyword argument
|
|
11
|
+
- Detection now uses parameter signature checking instead of gem-specific method detection
|
|
12
|
+
- Falls back to `Timeout.timeout` when monkey-patching is detected
|
|
13
|
+
- Detection result is cached for performance
|
|
14
|
+
|
|
15
|
+
- Fix network retry bug with `socket_max_failures: 0` (#1065)
|
|
16
|
+
- Previously, setting `socket_max_failures: 0` could still cause retries due to error handling
|
|
17
|
+
- Introduced `RetryableNetworkError` subclass to distinguish retryable vs non-retryable errors
|
|
18
|
+
- `down!` now raises non-retryable `NetworkError`, `reconnect!` raises `RetryableNetworkError`
|
|
19
|
+
- Thanks to Graham Cooper (Shopify) for this fix
|
|
20
|
+
|
|
21
|
+
- Fix "character class has duplicated range" Ruby warning (#1067)
|
|
22
|
+
- Fixed regex in `KeyManager::VALID_NAMESPACE_SEPARATORS` that caused warnings on newer Ruby versions
|
|
23
|
+
- Thanks to Hartley McGuire for this fix
|
|
24
|
+
|
|
25
|
+
Improvements:
|
|
26
|
+
|
|
27
|
+
- Add StrictWarnings test helper to catch Ruby warnings early (#1067)
|
|
28
|
+
|
|
29
|
+
- Use bulk attribute setter for OpenTelemetry spans (#1068)
|
|
30
|
+
- Reduces lock acquisitions when setting span attributes
|
|
31
|
+
- Thanks to Robert Laurin (Shopify) for this optimization
|
|
32
|
+
|
|
33
|
+
- Fix double recording of exceptions on OpenTelemetry spans (#1069)
|
|
34
|
+
- OpenTelemetry's `in_span` method already records exceptions and sets error status automatically
|
|
35
|
+
- Removed redundant explicit exception recording that caused exceptions to appear twice in traces
|
|
36
|
+
- Thanks to Robert Laurin (Shopify) for this fix
|
|
37
|
+
|
|
4
38
|
4.3.0
|
|
5
39
|
==========
|
|
6
40
|
|
data/Gemfile
CHANGED
data/lib/dalli/client.rb
CHANGED
|
@@ -522,8 +522,10 @@ module Dalli
|
|
|
522
522
|
def record_hit_miss_metrics(span, key_count, hit_count)
|
|
523
523
|
return unless span
|
|
524
524
|
|
|
525
|
-
span.
|
|
526
|
-
|
|
525
|
+
span.add_attributes({
|
|
526
|
+
'db.memcached.hit_count' => hit_count,
|
|
527
|
+
'db.memcached.miss_count' => key_count - hit_count
|
|
528
|
+
})
|
|
527
529
|
end
|
|
528
530
|
|
|
529
531
|
def get_multi_yielding(keys)
|
|
@@ -622,7 +624,7 @@ module Dalli
|
|
|
622
624
|
}) do
|
|
623
625
|
server.request(op, key, *args)
|
|
624
626
|
end
|
|
625
|
-
rescue
|
|
627
|
+
rescue RetryableNetworkError => e
|
|
626
628
|
Dalli.logger.debug { e.inspect }
|
|
627
629
|
Dalli.logger.debug { 'retrying request with new server' }
|
|
628
630
|
retry
|
|
@@ -90,12 +90,8 @@ module Dalli
|
|
|
90
90
|
def trace(name, attributes = {})
|
|
91
91
|
return yield unless enabled?
|
|
92
92
|
|
|
93
|
-
tracer.in_span(name, attributes: DEFAULT_ATTRIBUTES.merge(attributes), kind: :client) do |
|
|
93
|
+
tracer.in_span(name, attributes: DEFAULT_ATTRIBUTES.merge(attributes), kind: :client) do |_span|
|
|
94
94
|
yield
|
|
95
|
-
rescue StandardError => e
|
|
96
|
-
span.record_exception(e)
|
|
97
|
-
span.status = OpenTelemetry::Trace::Status.error(e.message)
|
|
98
|
-
raise
|
|
99
95
|
end
|
|
100
96
|
end
|
|
101
97
|
|
|
@@ -123,16 +119,10 @@ module Dalli
|
|
|
123
119
|
# results
|
|
124
120
|
# end
|
|
125
121
|
#
|
|
126
|
-
def trace_with_result(name, attributes = {})
|
|
122
|
+
def trace_with_result(name, attributes = {}, &)
|
|
127
123
|
return yield(nil) unless enabled?
|
|
128
124
|
|
|
129
|
-
tracer.in_span(name, attributes: DEFAULT_ATTRIBUTES.merge(attributes), kind: :client)
|
|
130
|
-
yield(span)
|
|
131
|
-
rescue StandardError => e
|
|
132
|
-
span.record_exception(e)
|
|
133
|
-
span.status = OpenTelemetry::Trace::Status.error(e.message)
|
|
134
|
-
raise
|
|
135
|
-
end
|
|
125
|
+
tracer.in_span(name, attributes: DEFAULT_ATTRIBUTES.merge(attributes), kind: :client, &)
|
|
136
126
|
end
|
|
137
127
|
end
|
|
138
128
|
end
|
data/lib/dalli/key_manager.rb
CHANGED
|
@@ -31,7 +31,7 @@ module Dalli
|
|
|
31
31
|
|
|
32
32
|
# Valid separators: non-alphanumeric, single printable ASCII characters
|
|
33
33
|
# Excludes: alphanumerics, whitespace, control characters
|
|
34
|
-
VALID_NAMESPACE_SEPARATORS = /\A[^a-zA-Z0-9\
|
|
34
|
+
VALID_NAMESPACE_SEPARATORS = /\A[^a-zA-Z0-9 \x00-\x1F\x7F]\z/
|
|
35
35
|
|
|
36
36
|
def initialize(client_options)
|
|
37
37
|
@key_options =
|
|
@@ -36,7 +36,7 @@ module Dalli
|
|
|
36
36
|
|
|
37
37
|
servers = fetch_responses(servers, start_time, @ring.socket_timeout, &block) until servers.empty?
|
|
38
38
|
end
|
|
39
|
-
rescue
|
|
39
|
+
rescue Dalli::RetryableNetworkError => e
|
|
40
40
|
Dalli.logger.debug { e.inspect }
|
|
41
41
|
Dalli.logger.debug { 'retrying pipelined gets because of timeout' }
|
|
42
42
|
retry
|
|
@@ -143,7 +143,7 @@ module Dalli
|
|
|
143
143
|
servers
|
|
144
144
|
rescue NetworkError
|
|
145
145
|
# Abort and raise if we encountered a network error. This triggers
|
|
146
|
-
# a retry at the top level.
|
|
146
|
+
# a retry at the top level on RetryableNetworkError.
|
|
147
147
|
abort_without_timeout(servers)
|
|
148
148
|
raise
|
|
149
149
|
end
|
|
@@ -28,7 +28,7 @@ module Dalli
|
|
|
28
28
|
servers = setup_requests(hash, ttl, req_options)
|
|
29
29
|
finish_requests(servers)
|
|
30
30
|
end
|
|
31
|
-
rescue
|
|
31
|
+
rescue Dalli::RetryableNetworkError => e
|
|
32
32
|
Dalli.logger.debug { e.inspect }
|
|
33
33
|
Dalli.logger.debug { 'retrying pipelined sets because of network error' }
|
|
34
34
|
retry
|
data/lib/dalli/socket.rb
CHANGED
|
@@ -90,6 +90,12 @@ module Dalli
|
|
|
90
90
|
# options - supports enhanced logging in the case of a timeout
|
|
91
91
|
attr_accessor :options
|
|
92
92
|
|
|
93
|
+
# Expected parameter signature for unmodified TCPSocket#initialize.
|
|
94
|
+
# Used to detect when gems like socksify or resolv-replace have monkey-patched
|
|
95
|
+
# TCPSocket, which breaks the connect_timeout: keyword argument.
|
|
96
|
+
TCPSOCKET_NATIVE_PARAMETERS = [[:rest]].freeze
|
|
97
|
+
private_constant :TCPSOCKET_NATIVE_PARAMETERS
|
|
98
|
+
|
|
93
99
|
def self.open(host, port, options = {})
|
|
94
100
|
create_socket_with_timeout(host, port, options) do |sock|
|
|
95
101
|
sock.options = { host: host, port: port }.merge(options)
|
|
@@ -99,15 +105,18 @@ module Dalli
|
|
|
99
105
|
end
|
|
100
106
|
end
|
|
101
107
|
|
|
108
|
+
# Detect and cache whether TCPSocket supports the connect_timeout: keyword argument.
|
|
109
|
+
# Returns false if TCPSocket#initialize has been monkey-patched by gems like
|
|
110
|
+
# socksify or resolv-replace, which don't support keyword arguments.
|
|
111
|
+
def self.supports_connect_timeout?
|
|
112
|
+
return @supports_connect_timeout if defined?(@supports_connect_timeout)
|
|
113
|
+
|
|
114
|
+
@supports_connect_timeout = RUBY_VERSION >= '3.0' &&
|
|
115
|
+
::TCPSocket.instance_method(:initialize).parameters == TCPSOCKET_NATIVE_PARAMETERS
|
|
116
|
+
end
|
|
117
|
+
|
|
102
118
|
def self.create_socket_with_timeout(host, port, options)
|
|
103
|
-
|
|
104
|
-
# (part of ruby standard library since 3.0.0, should be removed in 3.4.0),
|
|
105
|
-
# as it does not handle keyword arguments correctly.
|
|
106
|
-
# To check this we are using the fact that resolv-replace
|
|
107
|
-
# aliases TCPSocket#initialize method to #original_resolv_initialize.
|
|
108
|
-
# https://github.com/ruby/resolv-replace/blob/v0.1.1/lib/resolv-replace.rb#L21
|
|
109
|
-
if RUBY_VERSION >= '3.0' &&
|
|
110
|
-
!::TCPSocket.private_method_defined?(:original_resolv_initialize)
|
|
119
|
+
if supports_connect_timeout?
|
|
111
120
|
sock = new(host, port, connect_timeout: options[:socket_timeout])
|
|
112
121
|
yield(sock)
|
|
113
122
|
else
|
data/lib/dalli/version.rb
CHANGED
data/lib/dalli.rb
CHANGED
|
@@ -28,6 +28,9 @@ module Dalli
|
|
|
28
28
|
# raised when Memcached response with a SERVER_ERROR
|
|
29
29
|
class ServerError < DalliError; end
|
|
30
30
|
|
|
31
|
+
# socket/server communication error that can be retried
|
|
32
|
+
class RetryableNetworkError < NetworkError; end
|
|
33
|
+
|
|
31
34
|
# Implements the NullObject pattern to store an application-defined value for 'Key not found' responses.
|
|
32
35
|
class NilObject; end # rubocop:disable Lint/EmptyClass
|
|
33
36
|
NOT_FOUND = NilObject.new
|