Module: ResponseBank
- Defined in:
- lib/response_bank.rb,
lib/response_bank/railtie.rb,
lib/response_bank/version.rb,
lib/response_bank/controller.rb,
lib/response_bank/middleware.rb,
lib/response_bank/cache_policy.rb,
lib/response_bank/cache_writer.rb,
lib/response_bank/deferred_store.rb,
lib/response_bank/model_extensions.rb,
lib/response_bank/brotli_splice_slot.rb,
lib/response_bank/brotli_splice_injector.rb,
lib/response_bank/response_cache_handler.rb
Defined Under Namespace
Modules: BrotliSpliceInjector, BrotliSpliceSlot, Controller, ModelExtensions
Classes: DeferredStore, Middleware, Railtie, ResponseCacheHandler
Constant Summary
collapse
- VERSION =
"1.4.0"
["Location", "Content-Type", "ETag", "Content-Encoding", "Last-Modified", "Cache-Control", "Expires", "Link", "Surrogate-Keys", "Cache-Tags", "Speculation-Rules"].freeze
- CACHEABLE_STATUSES =
[200, 404, 301].freeze
- DEFAULT_BROTLI_COMPRESSION_LEVEL =
7
- DEFAULT_COMPRESSION_LEVEL =
-> (env, ) {
case env['response_bank.server_cache_encoding']
when 'br'
DEFAULT_BROTLI_COMPRESSION_LEVEL
when 'gzip'
Zlib::BEST_COMPRESSION
end
}
Class Attribute Summary collapse
Class Method Summary
collapse
-
.acquire_lock(_cache_key) ⇒ Object
-
.cache_key_for(data) ⇒ Object
-
.check_encoding(env, default_encoding = 'br') ⇒ Object
-
.compress(content, encoding = "br", compression_level: nil) ⇒ Object
-
.compression_level_for_request(env, headers) ⇒ Object
-
.decompress(content, encoding = "br") ⇒ Object
-
.defer_store(env, timestamp: Time.now.to_i) ⇒ Object
Starts a one-shot deferred cache fill for the current ResponseBank miss.
-
.log(message) ⇒ Object
-
.measure ⇒ Object
-
.read_from_backing_cache_store(_env, cache_key, backing_cache_store: cache_store) ⇒ Object
-
.release_lock(_cache_key) ⇒ Object
Override when deferred fills must release an application-managed lock.
-
.write_to_backing_cache_store(_env, key, payload, expires_in: nil) ⇒ Object
-
.write_to_cache(_key) ⇒ Object
Class Attribute Details
.cache_store ⇒ Object
Returns the value of attribute cache_store.
18
19
20
|
# File 'lib/response_bank.rb', line 18
def cache_store
@cache_store
end
|
.compression_level=(value) ⇒ Object
Sets the attribute compression_level
19
20
21
|
# File 'lib/response_bank.rb', line 19
def compression_level=(value)
@compression_level = value
end
|
.logger=(value) ⇒ Object
Sets the attribute logger
19
20
21
|
# File 'lib/response_bank.rb', line 19
def logger=(value)
@logger = value
end
|
Class Method Details
.acquire_lock(_cache_key) ⇒ Object
44
45
46
|
# File 'lib/response_bank.rb', line 44
def acquire_lock(_cache_key)
raise NotImplementedError, "Override ResponseBank.acquire_lock in an initializer."
end
|
.cache_key_for(data) ⇒ Object
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
# File 'lib/response_bank.rb', line 112
def cache_key_for(data)
case data
when Hash
return data.inspect unless data.key?(:key)
key = hash_value_str(data[:key])
key = %{#{data[:key_schema_version]}:#{key}} if data[:key_schema_version]
key = %{#{key}:#{hash_value_str(data[:version])}} if data[:version]
key = %{#{key}:#{hash_value_str(data[:encoding])}} if data[:encoding]
key
when Array
data.inspect
when Time, DateTime
data.to_i
when Date
data.to_s when true, false, Integer, Symbol, String
data.inspect
else
data.to_s.inspect
end
end
|
.check_encoding(env, default_encoding = 'br') ⇒ Object
140
141
142
143
144
145
146
147
148
149
|
# File 'lib/response_bank.rb', line 140
def check_encoding(env, default_encoding = 'br')
if env['HTTP_ACCEPT_ENCODING'].to_s.include?('br')
'br'
elsif env['HTTP_ACCEPT_ENCODING'].to_s.include?('gzip')
'gzip'
else
default_encoding
end
end
|
.compress(content, encoding = "br", compression_level: nil) ⇒ Object
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
|
# File 'lib/response_bank.rb', line 77
def compress(content, encoding = "br", compression_level: nil)
case encoding
when 'gzip'
attempts = 0
begin
Zlib.gzip(content, level: compression_level || Zlib::BEST_COMPRESSION)
rescue Zlib::BufError
attempts += 1
if attempts <= 1
retry
else
raise
end
end
when 'br'
Brotli.deflate(content, mode: :text, quality: compression_level || DEFAULT_BROTLI_COMPRESSION_LEVEL)
else
raise ArgumentError, "Unsupported encoding: #{encoding}"
end
end
|
.compression_level_for_request(env, headers) ⇒ Object
32
33
34
35
36
37
38
|
# File 'lib/response_bank.rb', line 32
def compression_level_for_request(env, )
if @compression_level
return @compression_level.respond_to?(:call) ? @compression_level.call(env, ) : @compression_level
end
DEFAULT_COMPRESSION_LEVEL.call(env, )
end
|
.decompress(content, encoding = "br") ⇒ Object
101
102
103
104
105
106
107
108
109
110
|
# File 'lib/response_bank.rb', line 101
def decompress(content, encoding = "br")
case encoding
when 'gzip'
Zlib.gunzip(content)
when 'br'
Brotli.inflate(content)
else
raise ArgumentError, "Unsupported encoding: #{encoding}"
end
end
|
.defer_store(env, timestamp: Time.now.to_i) ⇒ Object
Starts a one-shot deferred cache fill for the current ResponseBank miss.
Complete it only after the intended shared response was generated and
written successfully. Abort failed, disconnected or truncated responses.
51
52
53
|
# File 'lib/response_bank.rb', line 51
def defer_store(env, timestamp: Time.now.to_i)
DeferredStore.create(env, timestamp: timestamp)
end
|
.log(message) ⇒ Object
40
41
42
|
# File 'lib/response_bank.rb', line 40
def log(message)
@logger.info("[ResponseBank] #{message}")
end
|
.measure ⇒ Object
71
72
73
74
75
|
# File 'lib/response_bank.rb', line 71
def measure
Benchmark.realtime do
yield
end * 1000 end
|
.read_from_backing_cache_store(_env, cache_key, backing_cache_store: cache_store) ⇒ Object
67
68
69
|
# File 'lib/response_bank.rb', line 67
def read_from_backing_cache_store(_env, cache_key, backing_cache_store: cache_store)
backing_cache_store.read(cache_key, raw: true)
end
|
.release_lock(_cache_key) ⇒ Object
Override when deferred fills must release an application-managed lock.
56
57
|
# File 'lib/response_bank.rb', line 56
def release_lock(_cache_key)
end
|
.write_to_backing_cache_store(_env, key, payload, expires_in: nil) ⇒ Object
63
64
65
|
# File 'lib/response_bank.rb', line 63
def write_to_backing_cache_store(_env, key, payload, expires_in: nil)
cache_store.write(key, payload, raw: true, expires_in: expires_in)
end
|
.write_to_cache(_key) ⇒ Object
59
60
61
|
# File 'lib/response_bank.rb', line 59
def write_to_cache(_key)
yield
end
|