Class: Wurk::Lua::Loader
- Inherits:
-
Object
- Object
- Wurk::Lua::Loader
- Defined in:
- lib/wurk/lua/loader.rb
Overview
EVALSHA wrapper with NOSCRIPT recovery. The SHA1 of each script
source is precomputed in Wurk::Lua::SHAS, so the first call to
eval_cached after a fork has a fast path: a single EVALSHA, no
per-pool bookkeeping. If the script cache was flushed (manual
SCRIPT FLUSH, replica failover, OOM eviction), EVALSHA returns
NOSCRIPT — we then SCRIPT LOAD once and retry exactly once.
Spec: docs/target/sidekiq-free.md §20 (Lua script caching).
Constant Summary collapse
- NOSCRIPT_PREFIX =
'NOSCRIPT'
Class Method Summary collapse
-
.eval_cached(redis, name, keys:, argv:) ⇒ Object
Lua script return value.
-
.eval_with_source(redis, name, keys:, argv:) ⇒ Object
Source-embedded EVAL — the slow but cache-independent counterpart to
eval_cached. -
.script_load_all(redis) ⇒ Object
Eagerly upload every registered script to the given connection in a single pipelined round-trip (all SCRIPT LOADs, one RTT — not one per script).
Class Method Details
.eval_cached(redis, name, keys:, argv:) ⇒ Object
Returns Lua script return value.
36 37 38 39 40 41 42 43 44 45 |
# File 'lib/wurk/lua/loader.rb', line 36 def eval_cached(redis, name, keys:, argv:) src = SCRIPTS.fetch(name) { raise ArgumentError, "unknown Lua script: #{name.inspect}" } sha = SHAS.fetch(name) evalsha(redis, sha, keys, argv) rescue RedisClient::CommandError => e raise unless noscript?(e) redis.call('SCRIPT', 'LOAD', src) evalsha(redis, sha, keys, argv) end |
.eval_with_source(redis, name, keys:, argv:) ⇒ Object
Source-embedded EVAL — the slow but cache-independent counterpart to
eval_cached. Used on retry from a pipelined NOSCRIPT recovery where
EVALSHA can still race a freshly-loaded script under heavy CI load
(cf. WorkerTest NOSCRIPT flake on test (3.4, 7.2)). EVAL ships the
full source every call, so it never raises NOSCRIPT.
52 53 54 55 |
# File 'lib/wurk/lua/loader.rb', line 52 def eval_with_source(redis, name, keys:, argv:) src = SCRIPTS.fetch(name) { raise ArgumentError, "unknown Lua script: #{name.inspect}" } redis.call('EVAL', src, keys.size, *keys, *argv) end |
.script_load_all(redis) ⇒ Object
Eagerly upload every registered script to the given connection in a
single pipelined round-trip (all SCRIPT LOADs, one RTT — not one per
script). Idempotent on the Redis side: SCRIPT LOAD of the same source
returns the same SHA no matter how often it runs. ChildBoot calls this
once per child right after the post-fork reconnect so the first real
EVALSHA hits a warm cache instead of paying a NOSCRIPT reload. Transient
connection errors are the pool wrapper's job (Wurk::RedisPool#with);
this only ships the loads.
25 26 27 28 29 |
# File 'lib/wurk/lua/loader.rb', line 25 def script_load_all(redis) redis.pipelined do |pipe| SCRIPTS.each_value { |src| pipe.call('SCRIPT', 'LOAD', src) } end end |