Skip to content

Bump dalli from 3.2.15 to 5.3.2 - #67

Open
dependabot[bot] wants to merge 1 commit into
mainfrom
dependabot/bundler/dalli-5.3.2
Open

dependabot[bot] wants to merge 1 commit into
mainfrom
dependabot/bundler/dalli-5.3.2

Conversation

@dependabot

@dependabot dependabot Bot commented on behalf of github Nov 14, 2026

Copy link
Copy Markdown
Contributor

Bumps dalli from 3.2.15 to 5.3.2.

Release notes

Sourced from dalli's releases.

v5.3.2

Bug fixes:

  • A signal arriving while Dalli::Compressor or Dalli::GzipCompressorruby/zlib#49Zlib::BufError or Zlib::DataError, or stored a truncated value that later failed to decompress. Both compressors now keep finishing the stream until zlib reports its end. GzipCompressor no longer goes through GzipWriter and GzipReader, so it now always returns decompressed values as binary strings, as Compressor does (#1299)

v5.3.1

Bug fixes:

  • Rack::Session::Dalli's 401 for a session deleted mid-request called Hash#slice on the session options. A Rails session store puts an ActionDispatch::Request::Session::Options there, so the 401 raised NoMethodError instead of expiring the cookie (#1291, @​seballot)

v5.3.0

New features:

  • enforce_read_timeout: true makes JRuby and TruffleRuby give up waiting for a reply after socket_timeout, as CRuby does. Without it, a server that accepted a request but never replied blocked the caller indefinitely on those engines, including in get and get_multi. A server that stops partway through a reply can still block. It's off by default because it costs about 8% of single-key throughput on TruffleRuby and 20-29% on JRuby, and it has no effect on CRuby or TLS connections

Bug fixes:

  • A vivify_ttl (or fetch_with_lock's lock_ttl) over 30 days now protects against a thundering herd. memcached reads a TTL over 30 days as a Unix timestamp, so the stub for a miss expired at once and every caller won the recache race. vivify_ttl is now converted like other TTLs
  • set_cas, replace_cas and delete_cas dropped a CAS that couldn't be parsed, such as 'abc', and sent an unconditional write, so the value was overwritten or deleted whatever its CAS. They now raise ArgumentError
  • flush('abc') flushed immediately. It now raises ArgumentError
  • A TTL String that isn't a whole number, such as 'abc', became 0, which means no expiry. It now raises ArgumentError, including for expires_in when the client is created
  • A TTL, CAS, incr/decr amount or initial value outside the range memcached accepts got a CLIENT_ERROR reply, which a quiet block or set_multi discarded, so the write silently did nothing. These now raise ArgumentError
  • An invalid vivify_ttl or recache_ttl raised from deep in the request and closed the connection
  • tombstone_ttl read a String with a leading zero as octal ('010' was 8) and accepted hex such as '0x10'. It's now parsed in base 10 like every other TTL, and Float::NAN raises ArgumentError rather than FloatDomainError
  • Multi-gets now raise Dalli::UnmarshalError for a value that can't be deserialized, as get does, and only after reading the rest of the replies
    • get_multi and get_multi_cas raised partway through reading a server's replies, closing the connection, and get_multi_with_metadata on more than one server silently dropped every key on that server. A large get_multi could also drop that server's keys without raising when it read the bad value while still sending requests (seen mostly on JRuby and TruffleRuby)
    • In block form the other values are still yielded, and the connections stay open. get and the other single-key reads also keep the connection open after this error now
  • get_multi, get_multi_cas and get_multi_with_metadata now return each value under the key the caller passed. They rebuilt the key from the one memcached returned, so:
    • With a namespace, a key that isn't valid UTF-8 (such as "\xff".b) raised ArgumentError for the whole call
    • A key too long to send as is (over 250 bytes, or once base64-encoded) came back under its digested form
    • A binary key with non-ASCII bytes came back tagged UTF-8, so result.key?(key) was false
    • A key given more than once is now requested once, and a block is yielded it once
  • On TruffleRuby, a process spawned while Dalli had a connection open (with system, spawn or backticks) inherited the socket and kept the connection open on memcached's side until it exited. Dalli's sockets are now close-on-exec, as CRuby makes them by default
  • A request that failed after it was sent, such as one whose reply timed out, was sent again even though memcached may have applied it. incr, decr, append and prepend could be applied twice, and add and writes with a CAS could report failure for a write that had succeeded. Once some of a request has been sent, Dalli now retries only requests that are safe to apply twice (see Other changes)
  • When a server stopped while connected, the multi-key operations (get_multi, get_multi_cas, get_multi_with_metadata, set_multi and delete_multi) returned its keys as misses, or left them unwritten, instead of raising Dalli::NetworkError as documented. The retry found the server down and skipped it as if it had been down from the start. Without failover they now raise. With failover the keys still go to another server, as they do for get and set, when the retry can't connect to the failed server. A server that accepts the retry's connection and fails again is marked down during the operation, which raises Dalli::NetworkError either way (#1263, @​jaideeppyne)
  • Rack::Session::Dalli: a stored session that couldn't be decoded (for example after changing the serializer, or removing a class that sessions stored) left the user on a session that was never saved, with no new cookie, so they couldn't log in until the cookie was cleared or the session expired. It's now treated as missing: the request gets a new session and cookie, and a warning is logged
  • A reply value is now checked for the CRLF that should follow it. Values were read by their declared size alone, so a size that didn't match the value (a broken proxy, or an injected reply) was returned as a hit with a nil value, or the rest of the value was read as the next reply. These now raise Dalli::DalliError and close the connection, as a value size out of range does
  • get_multi_cas, and get_multi on more than one server, returned a server's keys as misses when it sent nothing within socket_timeout, without retrying or counting a failure. They now treat it like any read timeout: the batch is retried, and Dalli::NetworkError is raised once the server is marked down, as get, get_multi_with_metadata and single-server get_multi already did. socket_timeout also used to cover the whole batch, so a large reply that was still arriving could be cut off, with its remaining keys returned as misses. The wait now starts again whenever data arrives (#1285)
  • A reply key marked base64 that isn't valid base64 raised ArgumentError from get_multi, get_multi_cas and get_multi_with_metadata, which callers rescuing Dalli::DalliError didn't catch. It now raises Dalli::DalliError. Found by the new fuzz targets
  • set_multi and delete_multi on more than one server retried forever, hanging the caller, when a server accepted their writes and then closed the connection before replying. Each quiet write reset the server's failure count, so it never reached socket_max_failures. Only a request whose reply is read resets it now, and the server is marked down and Dalli::NetworkError raised, as for get
  • Since 5.2.0, on JRuby with TLS, Dalli could wait socket_timeout for part of a reply that had already arrived, because jruby-openssl can hold it where neither IO.select nor OpenSSL's pending reports it. With the multi-get change above (#1285), that wait would have made get_multi raise Dalli::NetworkError. Dalli now reads on JRuby until the TLS socket would block

Other changes:

  • Rack::Session::Dalli docs: without expire_after, sessions are stored with no expiry and stay in memcached until deleted or evicted
  • Numeric arguments are checked before anything is written, so a bad one raises ArgumentError without affecting the connection or earlier writes in a quiet block. Integers and Strings of decimal digits (such as '300') are accepted throughout
    • A TTL (ttl, expires_in, vivify_ttl, lock_ttl, tombstone_ttl) must fit memcached's signed 32-bit expiration time once a TTL over 30 days is converted to a Unix time. A negative TTL is still accepted and expires the item. A Float or ActiveSupport::Duration TTL is still converted with to_i
    • A CAS, an incr/decr amount or initial value, and a flush delay must be from 0 to 2**64 - 1. A Float now raises; incr(key, 0.9) used to truncate the amount to 0. A String amount such as '5' now works
    • fetch, fetch_with_lock, cas and cas! check ttl before running the block, so a bad one raises before any side effects. fetch checks it on a hit too
    • Dalli::Protocol::TtlSanitizer.sanitize raises ArgumentError for a String that isn't a whole number instead of returning 0

... (truncated)

Changelog

Sourced from dalli's changelog.

5.3.2

Bug fixes:

  • A signal arriving while Dalli::Compressor or Dalli::GzipCompressorruby/zlib#49Zlib::BufError or Zlib::DataError, or stored a truncated value that later failed to decompress. Both compressors now keep finishing the stream until zlib reports its end. GzipCompressor no longer goes through GzipWriter and GzipReader, so it now always returns decompressed values as binary strings, as Compressor does (#1299)

5.3.1

Bug fixes:

  • Rack::Session::Dalli's 401 for a session deleted mid-request called Hash#slice on the session options. A Rails session store puts an ActionDispatch::Request::Session::Options there, so the 401 raised NoMethodError instead of expiring the cookie (#1291, @​seballot)

5.3.0

New features:

  • enforce_read_timeout: true makes JRuby and TruffleRuby give up waiting for a reply after socket_timeout, as CRuby does. Without it, a server that accepted a request but never replied blocked the caller indefinitely on those engines, including in get and get_multi. A server that stops partway through a reply can still block. It's off by default because it costs about 8% of single-key throughput on TruffleRuby and 20-29% on JRuby, and it has no effect on CRuby or TLS connections

Bug fixes:

  • A vivify_ttl (or fetch_with_lock's lock_ttl) over 30 days now protects against a thundering herd. memcached reads a TTL over 30 days as a Unix timestamp, so the stub for a miss expired at once and every caller won the recache race. vivify_ttl is now converted like other TTLs
  • set_cas, replace_cas and delete_cas dropped a CAS that couldn't be parsed, such as 'abc', and sent an unconditional write, so the value was overwritten or deleted whatever its CAS. They now raise ArgumentError
  • flush('abc') flushed immediately. It now raises ArgumentError
  • A TTL String that isn't a whole number, such as 'abc', became 0, which means no expiry. It now raises ArgumentError, including for expires_in when the client is created
  • A TTL, CAS, incr/decr amount or initial value outside the range memcached accepts got a CLIENT_ERROR reply, which a quiet block or set_multi discarded, so the write silently did nothing. These now raise ArgumentError
  • An invalid vivify_ttl or recache_ttl raised from deep in the request and closed the connection
  • tombstone_ttl read a String with a leading zero as octal ('010' was 8) and accepted hex such as '0x10'. It's now parsed in base 10 like every other TTL, and Float::NAN raises ArgumentError rather than FloatDomainError
  • Multi-gets now raise Dalli::UnmarshalError for a value that can't be deserialized, as get does, and only after reading the rest of the replies
    • get_multi and get_multi_cas raised partway through reading a server's replies, closing the connection, and get_multi_with_metadata on more than one server silently dropped every key on that server. A large get_multi could also drop that server's keys without raising when it read the bad value while still sending requests (seen mostly on JRuby and TruffleRuby)
    • In block form the other values are still yielded, and the connections stay open. get and the other single-key reads also keep the connection open after this error now
  • get_multi, get_multi_cas and get_multi_with_metadata now return each value under the key the caller passed. They rebuilt the key from the one memcached returned, so:
    • With a namespace, a key that isn't valid UTF-8 (such as "\xff".b) raised ArgumentError for the whole call
    • A key too long to send as is (over 250 bytes, or once base64-encoded) came back under its digested form
    • A binary key with non-ASCII bytes came back tagged UTF-8, so result.key?(key) was false
    • A key given more than once is now requested once, and a block is yielded it once
  • On TruffleRuby, a process spawned while Dalli had a connection open (with system, spawn or backticks) inherited the socket and kept the connection open on memcached's side until it exited. Dalli's sockets are now close-on-exec, as CRuby makes them by default
  • A request that failed after it was sent, such as one whose reply timed out, was sent again even though memcached may have applied it. incr, decr, append and prepend could be applied twice, and add and writes with a CAS could report failure for a write that had succeeded. Once some of a request has been sent, Dalli now retries only requests that are safe to apply twice (see Other changes)
  • When a server stopped while connected, the multi-key operations (get_multi, get_multi_cas, get_multi_with_metadata, set_multi and delete_multi) returned its keys as misses, or left them unwritten, instead of raising Dalli::NetworkError as documented. The retry found the server down and skipped it as if it had been down from the start. Without failover they now raise. With failover the keys still go to another server, as they do for get and set, when the retry can't connect to the failed server. A server that accepts the retry's connection and fails again is marked down during the operation, which raises Dalli::NetworkError either way (#1263, @​jaideeppyne)
  • Rack::Session::Dalli: a stored session that couldn't be decoded (for example after changing the serializer, or removing a class that sessions stored) left the user on a session that was never saved, with no new cookie, so they couldn't log in until the cookie was cleared or the session expired. It's now treated as missing: the request gets a new session and cookie, and a warning is logged
  • A reply value is now checked for the CRLF that should follow it. Values were read by their declared size alone, so a size that didn't match the value (a broken proxy, or an injected reply) was returned as a hit with a nil value, or the rest of the value was read as the next reply. These now raise Dalli::DalliError and close the connection, as a value size out of range does
  • get_multi_cas, and get_multi on more than one server, returned a server's keys as misses when it sent nothing within socket_timeout, without retrying or counting a failure. They now treat it like any read timeout: the batch is retried, and Dalli::NetworkError is raised once the server is marked down, as get, get_multi_with_metadata and single-server get_multi already did. socket_timeout also used to cover the whole batch, so a large reply that was still arriving could be cut off, with its remaining keys returned as misses. The wait now starts again whenever data arrives (#1285)
  • A reply key marked base64 that isn't valid base64 raised ArgumentError from get_multi, get_multi_cas and get_multi_with_metadata, which callers rescuing Dalli::DalliError didn't catch. It now raises Dalli::DalliError. Found by the new fuzz targets
  • set_multi and delete_multi on more than one server retried forever, hanging the caller, when a server accepted their writes and then closed the connection before replying. Each quiet write reset the server's failure count, so it never reached socket_max_failures. Only a request whose reply is read resets it now, and the server is marked down and Dalli::NetworkError raised, as for get
  • Since 5.2.0, on JRuby with TLS, Dalli could wait socket_timeout for part of a reply that had already arrived, because jruby-openssl can hold it where neither IO.select nor OpenSSL's pending reports it. With the multi-get change above (#1285), that wait would have made get_multi raise Dalli::NetworkError. Dalli now reads on JRuby until the TLS socket would block

Other changes:

... (truncated)

Commits
  • 9d8c380 Prepare 5.3.2 release (#1303)
  • cba8746 Finish zlib streams that a signal interrupts (#1300)
  • 2ef90c3 Tick the credentials and get_multi retry follow-ups in the hardening plan (#1...
  • 498c997 Prepare 5.3.1 release (#1296)
  • ec5ab3a Expire the session cookie when Rails session options are not a Hash (#1291)
  • 4bbd037 Prepare 5.3.0 release (#1292)
  • 6009faa Read JRuby TLS sockets until they would block (#1293)
  • d6bc9f5 Retry and raise when a server sends nothing to a multi-get (#1289)
  • e0e2aaf Stop set_multi and delete_multi retrying forever on a dropped connection (#1288)
  • 3cce253 Restore quiet set throughput with fast paths for valid TTLs and CAS (#1290)
  • Additional commits viewable in compare view

Dependabot compatibility score

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


Dependabot commands and options

You can trigger Dependabot actions by commenting on this PR:

  • @dependabot rebase will rebase this PR
  • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
  • @dependabot show <dependency name> ignore conditions will show all of the ignore conditions of the specified dependency
  • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
  • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
  • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)

Bumps [dalli](https://github.com/petergoldstein/dalli) from 3.2.15 to 5.3.2.
- [Release notes](https://github.com/petergoldstein/dalli/releases)
- [Changelog](https://github.com/petergoldstein/dalli/blob/main/CHANGELOG.md)
- [Commits](petergoldstein/dalli@v3.2.15...v5.3.2)

---
updated-dependencies:
- dependency-name: dalli
  dependency-version: 5.3.2
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <[email protected]>
@dependabot dependabot Bot added dependencies Pull requests that update a dependency file ruby Pull requests that update ruby code labels Nov 14, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file ruby Pull requests that update ruby code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants