Class: Redstruct::Script
- Inherits:
-
Object
- Object
- Redstruct::Script
- Defined in:
- lib/redstruct/script.rb
Overview
Utility class to interact with Lua scripts on Redis. It is recommended you flush your script cache on the redis server every once in a while to remove scripts that are not used anymore.
Constant Summary
- ERROR_MESSAGE_PREFIX =
Redis returns an error starting with NOSCRIPT when we try to evaluate am unknown script using its sha1.
'NOSCRIPT'
Instance Attribute Summary collapse
-
#connection ⇒ Redstruct::ConnectionProxy
readonly
The connection used for script commands.
-
#script ⇒ String
The Lua script to evaluate.
Instance Method Summary collapse
-
#eval(keys: [], argv: []) ⇒ nil, ...
Evaluates the script using the given keys and argv arrays, and returns the unparsed result.
-
#exists? ⇒ Boolean
Checks if the script was already loaded for the given redis db using #sha1.
-
#initialize(script:, connection:, sha1: nil) ⇒ Script
constructor
A new instance of Script.
-
#load ⇒ String
Loads the given script to redis (i.e. sends the source, which gets compiled and saved) and saves the returned sha1.
-
#sha1 ⇒ String
Returns the sha1 representation of the source code at `script` When running a lua script, redis will compile it once and cache the bytecode, using the sha1 of the source code as the cache key.
Constructor Details
#initialize(script:, connection:, sha1: nil) ⇒ Script
Returns a new instance of Script
25 26 27 28 29 30 31 |
# File 'lib/redstruct/script.rb', line 25 def initialize(script:, connection:, sha1: nil) self.script = script @connection = connection @sha1 = sha1 unless sha1.nil? raise ArgumentError, 'requires a connection proxy' unless @connection.is_a?(Redstruct::ConnectionProxy) end |
Instance Attribute Details
#connection ⇒ Redstruct::ConnectionProxy (readonly)
Returns the connection used for script commands
20 21 22 |
# File 'lib/redstruct/script.rb', line 20 def connection @connection end |
#script ⇒ String
Returns the Lua script to evaluate
17 18 19 |
# File 'lib/redstruct/script.rb', line 17 def script @script end |
Instance Method Details
#eval(keys: [], argv: []) ⇒ nil, ...
Evaluates the script using the given keys and argv arrays, and returns the unparsed result. Caller is in charge of interpreting the result. NOTE: To minimize the number of redis commands, this always first assumes that the script was already loaded using its sha1 representation, and tells redis to execute the script cached by `sha1`. If it receives as error that the script does not exist, only then will it send the source to be executed. So in the worst case you get 2 redis commands, but in the average case you get 1, and it's much faster as redis does not have to reparse the script, and we don't need to send the lua source every time.
76 77 78 79 80 81 82 83 84 85 |
# File 'lib/redstruct/script.rb', line 76 def eval(keys: [], argv: []) keys = [keys] unless keys.is_a?(Array) argv = [argv] unless argv.is_a?(Array) argv = normalize(argv) @connection.evalsha(self.sha1, keys, argv) rescue Redis::CommandError => err raise unless err..start_with?(ERROR_MESSAGE_PREFIX) @connection.eval(@script, keys, argv) end |
#exists? ⇒ Boolean
Checks if the script was already loaded for the given redis db using #sha1
55 56 57 |
# File 'lib/redstruct/script.rb', line 55 def exists? return @connection.script(:exists, self.sha1) end |
#load ⇒ String
Loads the given script to redis (i.e. sends the source, which gets compiled and saved) and saves the returned sha1
61 62 63 64 |
# File 'lib/redstruct/script.rb', line 61 def load @sha1 = @connection.script(:load, @script) return @sha1 end |
#sha1 ⇒ String
Returns the sha1 representation of the source code at `script` When running a lua script, redis will compile it once and cache the bytecode, using the sha1 of the source code as the cache key.
47 48 49 50 51 |
# File 'lib/redstruct/script.rb', line 47 def sha1 return @sha1 ||= begin Digest::SHA1.hexdigest(@script) end end |