Class: Familia::Migration::Script
- Inherits:
-
Object
- Object
- Familia::Migration::Script
- Defined in:
- lib/familia/migration/script.rb
Overview
Lua script registry for atomic Redis operations during migrations.
Provides class-level registration and execution of Lua scripts with EVALSHA/EVAL fallback pattern for efficiency. Scripts are precomputed with their SHA1 hashes at registration time.
Defined Under Namespace
Classes: ScriptError, ScriptNotFound
Constant Summary collapse
- ScriptEntry =
Holds script source and precomputed SHA1
Data.define(:source, :sha) do def initialize(source:, sha: nil) computed_sha = sha || Digest::SHA1.hexdigest(source) super(source: source.freeze, sha: computed_sha.freeze) end end
Class Method Summary collapse
-
.execute(redis, name, keys: [], argv: []) ⇒ Object
Execute a registered script with EVALSHA/EVAL fallback.
-
.preload_all(redis) ⇒ Hash{Symbol => String}
Preload all registered scripts to the Redis server.
-
.register(name, lua_source) ⇒ ScriptEntry
Register a Lua script with the given name.
-
.registered?(name) ⇒ Boolean
Check if a script is registered.
-
.reset! ⇒ void
Reset the registry (primarily for testing).
-
.scripts ⇒ Hash{Symbol => ScriptEntry}
Access the script registry.
-
.sha_for(name) ⇒ String?
Get the SHA for a registered script.
Class Method Details
.execute(redis, name, keys: [], argv: []) ⇒ Object
Execute a registered script with EVALSHA/EVAL fallback
Attempts EVALSHA first for efficiency. If the script is not cached on the Redis server (NOSCRIPT error), falls back to EVAL which also caches the script for future calls.
78 79 80 81 82 83 |
# File 'lib/familia/migration/script.rb', line 78 def execute(redis, name, keys: [], argv: []) entry = scripts[name] raise ScriptNotFound, "Script not found: #{name}" unless entry execute_with_fallback(redis, entry, keys, argv, name) end |
.preload_all(redis) ⇒ Hash{Symbol => String}
Preload all registered scripts to the Redis server
Loads scripts using SCRIPT LOAD so subsequent EVALSHA calls will succeed without fallback. Useful at application startup.
92 93 94 95 96 97 |
# File 'lib/familia/migration/script.rb', line 92 def preload_all(redis) scripts.each_with_object({}) do |(name, entry), loaded| sha = redis.script(:load, entry.source) loaded[name] = sha end end |
.register(name, lua_source) ⇒ ScriptEntry
Register a Lua script with the given name
56 57 58 59 60 61 62 63 |
# File 'lib/familia/migration/script.rb', line 56 def register(name, lua_source) raise ArgumentError, 'Script name must be a Symbol' unless name.is_a?(Symbol) raise ArgumentError, 'Lua source cannot be empty' if lua_source.nil? || lua_source.strip.empty? entry = ScriptEntry.new(source: lua_source.strip) scripts[name] = entry entry end |
.registered?(name) ⇒ Boolean
Check if a script is registered
103 104 105 |
# File 'lib/familia/migration/script.rb', line 103 def registered?(name) scripts.key?(name) end |
.reset! ⇒ void
This method returns an undefined value.
Reset the registry (primarily for testing)
118 119 120 121 |
# File 'lib/familia/migration/script.rb', line 118 def reset! @scripts = {} register_builtin_scripts end |
.scripts ⇒ Hash{Symbol => ScriptEntry}
Access the script registry
46 47 48 |
# File 'lib/familia/migration/script.rb', line 46 def scripts @scripts ||= {} end |
.sha_for(name) ⇒ String?
Get the SHA for a registered script
111 112 113 |
# File 'lib/familia/migration/script.rb', line 111 def sha_for(name) scripts[name]&.sha end |