From 790ec68f163e150f314bab4dfd859702455af804 Mon Sep 17 00:00:00 2001 From: Chris AtLee Date: Tue, 31 Oct 2023 15:49:03 +0000 Subject: [PATCH 1/3] WIP - use memcached's @connection.with_error_value --- lib/active_support/cache/memcached_store.rb | 20 +++++++++++++------- memcached_store.gemspec | 2 +- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/lib/active_support/cache/memcached_store.rb b/lib/active_support/cache/memcached_store.rb index 92fde8b..145f534 100644 --- a/lib/active_support/cache/memcached_store.rb +++ b/lib/active_support/cache/memcached_store.rb @@ -131,6 +131,8 @@ def read_multi(*names) end end + CAS_SENTINEL = Object.new + def cas(name, options = nil) options = merged_options(options) key = normalize_key(name, options) @@ -138,14 +140,16 @@ def cas(name, options = nil) success = handle_exceptions(return_value_on_error: false) do instrument(:cas, name, options) do - @connection.cas(key, expiration(options)) do |raw_value| - entry = deserialize_entry(raw_value) - value = yield entry.value - break true if read_only - payload = serialize_entry(Entry.new(value, **options), options) + @connection.with_error_value(CAS_SENTINEL) do + ret = @connection.cas(key, expiration(options)) do |raw_value| + entry = deserialize_entry(raw_value) + value = yield entry.value + break true if read_only + payload = serialize_entry(Entry.new(value, **options), options) + end + ret != CAS_SENTINEL end end - true end if success @@ -288,7 +292,9 @@ def read_entry(key, **options) # :nodoc: def read_serialized_entry(key, **) handle_exceptions(return_value_on_error: nil) do - @connection.get(key) + @connection.with_error_value(nil) do + @connection.get(key) + end end end diff --git a/memcached_store.gemspec b/memcached_store.gemspec index d2d1524..d6e2ff3 100644 --- a/memcached_store.gemspec +++ b/memcached_store.gemspec @@ -20,7 +20,7 @@ Gem::Specification.new do |spec| spec.required_ruby_version = ">= 2.6.0" spec.add_runtime_dependency "activesupport", ">= 6" - spec.add_runtime_dependency "memcached", "~> 1.8" + spec.add_runtime_dependency "memcached", ">= 1.10" spec.add_development_dependency "rake" spec.add_development_dependency "mocha" From f6d3214320f7cfdae348ef9f025674550fdf03d9 Mon Sep 17 00:00:00 2001 From: Chris AtLee Date: Fri, 3 Nov 2023 18:53:17 +0000 Subject: [PATCH 2/3] improve cas support --- Gemfile | 2 ++ lib/active_support/cache/memcached_store.rb | 16 ++++++++++------ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/Gemfile b/Gemfile index 1466767..fa4df2a 100644 --- a/Gemfile +++ b/Gemfile @@ -3,3 +3,5 @@ source 'https://rubygems.org' gemspec gem "snappy" + +gem "memcached", path: "../memcached" diff --git a/lib/active_support/cache/memcached_store.rb b/lib/active_support/cache/memcached_store.rb index 145f534..7180159 100644 --- a/lib/active_support/cache/memcached_store.rb +++ b/lib/active_support/cache/memcached_store.rb @@ -131,8 +131,6 @@ def read_multi(*names) end end - CAS_SENTINEL = Object.new - def cas(name, options = nil) options = merged_options(options) key = normalize_key(name, options) @@ -140,14 +138,18 @@ def cas(name, options = nil) success = handle_exceptions(return_value_on_error: false) do instrument(:cas, name, options) do - @connection.with_error_value(CAS_SENTINEL) do + @connection.without_exceptions do ret = @connection.cas(key, expiration(options)) do |raw_value| entry = deserialize_entry(raw_value) value = yield entry.value break true if read_only payload = serialize_entry(Entry.new(value, **options), options) end - ret != CAS_SENTINEL + # `cas` returns NOT_FOUND if the key doesn't exist, DATA_EXISTS if the key was modified by another client + # and it returns `nil` on success, + # + # Here we just want to return true/false if the key was set successfully, which is the case when `cas` returns nil + ret == nil end end end @@ -292,8 +294,10 @@ def read_entry(key, **options) # :nodoc: def read_serialized_entry(key, **) handle_exceptions(return_value_on_error: nil) do - @connection.with_error_value(nil) do - @connection.get(key) + @connection.without_exceptions do + val = @connection.get(key) + return nil if val == Memcached::NOT_FOUND + val end end end From 2eb3232f37c3dc3c51d335d298324b8172366629 Mon Sep 17 00:00:00 2001 From: Chris AtLee Date: Fri, 3 Nov 2023 19:09:01 +0000 Subject: [PATCH 3/3] temporary - point to alternate memcached --- Gemfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index fa4df2a..9394193 100644 --- a/Gemfile +++ b/Gemfile @@ -4,4 +4,5 @@ gemspec gem "snappy" -gem "memcached", path: "../memcached" +# gem "memcached", path: "../memcached" +gem "memcached", github: "Shopify/memcached", branch: "catlee/with_error_value"