dalli 4.0.0 → 4.0.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 +6 -0
- data/Gemfile +9 -2
- data/README.md +26 -0
- data/lib/dalli/client.rb +5 -0
- data/lib/dalli/protocol/base.rb +2 -2
- data/lib/dalli/protocol/connection_manager.rb +3 -3
- data/lib/dalli/protocol/string_marshaller.rb +65 -0
- data/lib/dalli/protocol.rb +10 -0
- data/lib/dalli/version.rb +1 -1
- data/lib/dalli.rb +1 -0
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5494b3c5f7ce6c73cb061511ab96c7dafc0ed1f5d10a865310a7adc79c8587c9
|
|
4
|
+
data.tar.gz: 1326cd38aad6ba7c7c0c65c2b0305b4c4c566e3a0050df1f8ccee6aa42ee2bc7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5affa5731ead45a7c352628c4c3c471b1fc5c7499e9e63e58278e2c59c309e90fd550774a8808de78ff9daaa53913503810ded029d0879f3a6408f19a4bf67f2
|
|
7
|
+
data.tar.gz: 244b909ac405e2f8757b3bfa3fdcea3fb17615f6d329527f63c3392a4921dd8298fa9d6eeaab368bd80112413c593d94f305062732fb28204072526b84eba3d4
|
data/CHANGELOG.md
CHANGED
data/Gemfile
CHANGED
|
@@ -5,11 +5,18 @@ source 'https://rubygems.org'
|
|
|
5
5
|
gemspec
|
|
6
6
|
|
|
7
7
|
group :development, :test do
|
|
8
|
+
gem 'benchmark'
|
|
8
9
|
gem 'cgi'
|
|
9
10
|
gem 'connection_pool'
|
|
10
11
|
gem 'debug' unless RUBY_PLATFORM == 'java'
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
if RUBY_VERSION >= '3.2'
|
|
13
|
+
gem 'minitest', '~> 6'
|
|
14
|
+
gem 'minitest-mock'
|
|
15
|
+
else
|
|
16
|
+
gem 'minitest', '~> 5'
|
|
17
|
+
end
|
|
18
|
+
gem 'rack', '~> 3'
|
|
19
|
+
gem 'rack-session'
|
|
13
20
|
gem 'rake', '~> 13.0'
|
|
14
21
|
gem 'rubocop'
|
|
15
22
|
gem 'rubocop-minitest'
|
data/README.md
CHANGED
|
@@ -14,6 +14,32 @@ Dalli supports:
|
|
|
14
14
|
|
|
15
15
|
The name is a variant of Salvador Dali for his famous painting [The Persistence of Memory](http://en.wikipedia.org/wiki/The_Persistence_of_Memory).
|
|
16
16
|
|
|
17
|
+
## Requirements
|
|
18
|
+
|
|
19
|
+
* Ruby 3.1 or later
|
|
20
|
+
* memcached 1.4 or later (1.6+ recommended for meta protocol support)
|
|
21
|
+
|
|
22
|
+
## Protocol Options
|
|
23
|
+
|
|
24
|
+
Dalli supports two protocols for communicating with memcached:
|
|
25
|
+
|
|
26
|
+
* `:binary` (default) - Works with all memcached versions, supports SASL authentication
|
|
27
|
+
* `:meta` - Requires memcached 1.6+, better performance for some operations, no authentication support
|
|
28
|
+
|
|
29
|
+
```ruby
|
|
30
|
+
Dalli::Client.new('localhost:11211', protocol: :meta)
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Security Note
|
|
34
|
+
|
|
35
|
+
By default, Dalli uses Ruby's Marshal for serialization. Deserializing untrusted data with Marshal can lead to remote code execution. If you cache user-controlled data, consider using a safer serializer:
|
|
36
|
+
|
|
37
|
+
```ruby
|
|
38
|
+
Dalli::Client.new('localhost:11211', serializer: JSON)
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
See the [4.0-Upgrade.md](4.0-Upgrade.md) guide for more information.
|
|
42
|
+
|
|
17
43
|

|
|
18
44
|
|
|
19
45
|
|
data/lib/dalli/client.rb
CHANGED
|
@@ -41,6 +41,11 @@ module Dalli
|
|
|
41
41
|
# - :compressor - defaults to Dalli::Compressor, a Zlib-based implementation
|
|
42
42
|
# - :cache_nils - defaults to false, if true Dalli will not treat cached nil values as 'not found' for
|
|
43
43
|
# #fetch operations.
|
|
44
|
+
# - :raw - If set, disables serialization and compression entirely at the client level.
|
|
45
|
+
# Only String values are supported. This is useful when the caller handles its own
|
|
46
|
+
# serialization (e.g., Rails' ActiveSupport::Cache). Note: this is different from
|
|
47
|
+
# the per-request :raw option which converts values to strings but still uses the
|
|
48
|
+
# serialization pipeline.
|
|
44
49
|
# - :digest_class - defaults to Digest::MD5, allows you to pass in an object that responds to the hexdigest method,
|
|
45
50
|
# useful for injecting a FIPS compliant hash object.
|
|
46
51
|
# - :protocol - one of either :binary or :meta, defaulting to :binary. This sets the protocol that Dalli uses
|
data/lib/dalli/protocol/base.rb
CHANGED
|
@@ -23,7 +23,7 @@ module Dalli
|
|
|
23
23
|
def initialize(attribs, client_options = {})
|
|
24
24
|
hostname, port, socket_type, @weight, user_creds = ServerConfigParser.parse(attribs)
|
|
25
25
|
@options = client_options.merge(user_creds)
|
|
26
|
-
@value_marshaller = ValueMarshaller.new(@options)
|
|
26
|
+
@value_marshaller = client_options[:raw] ? StringMarshaller.new(@options) : ValueMarshaller.new(@options)
|
|
27
27
|
@connection_manager = ConnectionManager.new(hostname, port, socket_type, @options)
|
|
28
28
|
end
|
|
29
29
|
|
|
@@ -106,7 +106,7 @@ module Dalli
|
|
|
106
106
|
end
|
|
107
107
|
|
|
108
108
|
values
|
|
109
|
-
rescue SystemCallError, *TIMEOUT_ERRORS, EOFError => e
|
|
109
|
+
rescue SystemCallError, *TIMEOUT_ERRORS, *SSL_ERRORS, EOFError => e
|
|
110
110
|
@connection_manager.error_on_request!(e)
|
|
111
111
|
end
|
|
112
112
|
|
|
@@ -150,19 +150,19 @@ module Dalli
|
|
|
150
150
|
data = @sock.gets("\r\n")
|
|
151
151
|
error_on_request!('EOF in read_line') if data.nil?
|
|
152
152
|
data
|
|
153
|
-
rescue SystemCallError, *TIMEOUT_ERRORS, EOFError => e
|
|
153
|
+
rescue SystemCallError, *TIMEOUT_ERRORS, *SSL_ERRORS, EOFError => e
|
|
154
154
|
error_on_request!(e)
|
|
155
155
|
end
|
|
156
156
|
|
|
157
157
|
def read(count)
|
|
158
158
|
@sock.readfull(count)
|
|
159
|
-
rescue SystemCallError, *TIMEOUT_ERRORS, EOFError => e
|
|
159
|
+
rescue SystemCallError, *TIMEOUT_ERRORS, *SSL_ERRORS, EOFError => e
|
|
160
160
|
error_on_request!(e)
|
|
161
161
|
end
|
|
162
162
|
|
|
163
163
|
def write(bytes)
|
|
164
164
|
@sock.write(bytes)
|
|
165
|
-
rescue SystemCallError, *TIMEOUT_ERRORS => e
|
|
165
|
+
rescue SystemCallError, *TIMEOUT_ERRORS, *SSL_ERRORS => e
|
|
166
166
|
error_on_request!(e)
|
|
167
167
|
end
|
|
168
168
|
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Dalli
|
|
4
|
+
module Protocol
|
|
5
|
+
##
|
|
6
|
+
# Dalli::Protocol::StringMarshaller is a pass-through marshaller for use with
|
|
7
|
+
# the :raw client option. It bypasses serialization and compression entirely,
|
|
8
|
+
# expecting values to already be strings (e.g., pre-serialized by Rails'
|
|
9
|
+
# ActiveSupport::Cache). It still enforces the maximum value size limit.
|
|
10
|
+
##
|
|
11
|
+
class StringMarshaller
|
|
12
|
+
DEFAULTS = {
|
|
13
|
+
# max size of value in bytes (default is 1 MB, can be overriden with "memcached -I <size>")
|
|
14
|
+
value_max_bytes: 1024 * 1024
|
|
15
|
+
}.freeze
|
|
16
|
+
|
|
17
|
+
attr_reader :value_max_bytes
|
|
18
|
+
|
|
19
|
+
def initialize(client_options)
|
|
20
|
+
@value_max_bytes = client_options.fetch(:value_max_bytes) do
|
|
21
|
+
DEFAULTS.fetch(:value_max_bytes)
|
|
22
|
+
end.to_i
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def store(key, value, _options = nil)
|
|
26
|
+
raise MarshalError, "Dalli in :raw mode only supports strings, got: #{value.class}" unless value.is_a?(String)
|
|
27
|
+
|
|
28
|
+
error_if_over_max_value_bytes(key, value)
|
|
29
|
+
[value, 0]
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def retrieve(value, _flags)
|
|
33
|
+
value
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Interface compatibility methods - these return nil since
|
|
37
|
+
# StringMarshaller bypasses serialization and compression entirely.
|
|
38
|
+
|
|
39
|
+
def serializer
|
|
40
|
+
nil
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def compressor
|
|
44
|
+
nil
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def compression_min_size
|
|
48
|
+
nil
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def compress_by_default?
|
|
52
|
+
false
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
private
|
|
56
|
+
|
|
57
|
+
def error_if_over_max_value_bytes(key, value)
|
|
58
|
+
return if value.bytesize <= value_max_bytes
|
|
59
|
+
|
|
60
|
+
message = "Value for #{key} over max size: #{value_max_bytes} <= #{value.bytesize}"
|
|
61
|
+
raise Dalli::ValueOverMaxSize, message
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
data/lib/dalli/protocol.rb
CHANGED
|
@@ -15,5 +15,15 @@ module Dalli
|
|
|
15
15
|
else
|
|
16
16
|
[Timeout::Error]
|
|
17
17
|
end
|
|
18
|
+
|
|
19
|
+
# SSL errors that occur during read/write operations (not during initial
|
|
20
|
+
# handshake) should trigger reconnection. These indicate transient network
|
|
21
|
+
# issues, not configuration problems.
|
|
22
|
+
SSL_ERRORS =
|
|
23
|
+
if defined?(OpenSSL::SSL::SSLError)
|
|
24
|
+
[OpenSSL::SSL::SSLError]
|
|
25
|
+
else
|
|
26
|
+
[]
|
|
27
|
+
end
|
|
18
28
|
end
|
|
19
29
|
end
|
data/lib/dalli/version.rb
CHANGED
data/lib/dalli.rb
CHANGED
|
@@ -72,6 +72,7 @@ require_relative 'dalli/protocol/server_config_parser'
|
|
|
72
72
|
require_relative 'dalli/protocol/ttl_sanitizer'
|
|
73
73
|
require_relative 'dalli/protocol/value_compressor'
|
|
74
74
|
require_relative 'dalli/protocol/value_marshaller'
|
|
75
|
+
require_relative 'dalli/protocol/string_marshaller'
|
|
75
76
|
require_relative 'dalli/protocol/value_serializer'
|
|
76
77
|
require_relative 'dalli/servers_arg_normalizer'
|
|
77
78
|
require_relative 'dalli/socket'
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: dalli
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 4.0.
|
|
4
|
+
version: 4.0.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Peter M. Goldstein
|
|
@@ -58,6 +58,7 @@ files:
|
|
|
58
58
|
- lib/dalli/protocol/meta/response_processor.rb
|
|
59
59
|
- lib/dalli/protocol/response_buffer.rb
|
|
60
60
|
- lib/dalli/protocol/server_config_parser.rb
|
|
61
|
+
- lib/dalli/protocol/string_marshaller.rb
|
|
61
62
|
- lib/dalli/protocol/ttl_sanitizer.rb
|
|
62
63
|
- lib/dalli/protocol/value_compressor.rb
|
|
63
64
|
- lib/dalli/protocol/value_marshaller.rb
|
|
@@ -88,7 +89,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
88
89
|
- !ruby/object:Gem::Version
|
|
89
90
|
version: '0'
|
|
90
91
|
requirements: []
|
|
91
|
-
rubygems_version: 4.0.
|
|
92
|
+
rubygems_version: 4.0.4
|
|
92
93
|
specification_version: 4
|
|
93
94
|
summary: High performance memcached client for Ruby
|
|
94
95
|
test_files: []
|