Skip to content

Commit b8b9104

Browse files
committed
Handle subsequent cache reads which are frozen
More quirks of the Rails cache. Initial testing showed that writing a frozen cache value returns an unfrozen value. Likely due to poor rigor in test methodology previous thought was that all reads of the cache would result in unfrozen values - even if that cache'd entry was refrozen. This turns out to be false. The actual behavior is: - Write frozen object to cache - Read cache receiving an unfrozen version - All subsequent cache reads will be unfrozen until one of the read versions is re-frozen - Subsequent cache reads will be frozen This was causing "500 Internal Server" errors in what appeared to be ActiveRecord calls. Digging into the stack trace showed it was our caching.
1 parent 735dace commit b8b9104

File tree

2 files changed

+27
-1
lines changed

2 files changed

+27
-1
lines changed

lib/kracken/controllers/token_authenticatable.rb

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,13 @@ def cache_valid_auth(token, &generate_cache)
4545
cache_key = "auth/token/#{token}"
4646
val = Rails.cache.read(cache_key)
4747
val ||= store_valid_auth(cache_key, &generate_cache)
48-
val.transform_values!(&:freeze).freeze if val
48+
shallow_freeze(val)
49+
end
50+
51+
def shallow_freeze(val)
52+
# nil is always frozen
53+
return val if val.frozen?
54+
val.transform_values!(&:freeze).freeze
4955
end
5056

5157
def current_auth_info

spec/kracken/controllers/token_authenticatable_spec.rb

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
require "rails_helper"
12
require "support/base_controller_double"
23
require "support/using_cache"
34

@@ -89,6 +90,25 @@ def authenticate_or_request_with_http_token(realm = nil)
8990
).and be_frozen
9091
end
9192

93+
it "handles already frozen auth hashes" do
94+
# This seems to happen on the 2nd cache read - despite the hash being
95+
# frozen when put into the cache the first cache read will not be
96+
# frozen. However, subsequent reads seem to be froze - this may be
97+
# Rails version dependent. Regardless, we need to be aware of it.
98+
99+
# Initial cache request
100+
expect(a_controller.authenticate_user_with_token!).to eq(
101+
id: :any_id,
102+
team_ids: [:some, :team, :ids],
103+
).and be_frozen
104+
105+
# Secondary cache request
106+
expect(a_controller.authenticate_user_with_token!).to eq(
107+
id: :any_id,
108+
team_ids: [:some, :team, :ids],
109+
).and be_frozen
110+
end
111+
92112
it "exposes the auth info via the `current_` helpers", :aggregate_failures do
93113
expect {
94114
a_controller.authenticate_user_with_token!

0 commit comments

Comments
 (0)