Class: Labkit::Redis::Script

Inherits:
Object
  • Object
show all
Defined in:
lib/labkit/redis/script.rb

Overview

Wraps a Lua script for EVALSHA-with-NOSCRIPT-fallback execution. The SHA is computed once at construction. Redis caches the script body the first time EVAL is invoked; subsequent EVALSHA calls hit that cache. SCRIPT FLUSH or a Redis restart drops the cache; the NOSCRIPT recovery re-ships the body and re-populates it.

Examples:

SCRIPT = Labkit::Redis::Script.new(<<~LUA)
  return redis.call('INCRBY', KEYS[1], ARGV[1])
LUA

pool.with { |conn| SCRIPT.eval(conn, keys: ["counter"], argv: [1]) }

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(body) ⇒ Script

Returns a new instance of Script.



23
24
25
26
27
28
# File 'lib/labkit/redis/script.rb', line 23

def initialize(body)
  @body = body.freeze
  # SHA1 is mandated by the Redis EVALSHA wire protocol, not a discretionary hash choice.
  @sha = OpenSSL::Digest::SHA1.hexdigest(body).freeze # rubocop:disable Fips/SHA1
  freeze
end

Instance Attribute Details

#bodyObject (readonly)

Returns the value of attribute body.



21
22
23
# File 'lib/labkit/redis/script.rb', line 21

def body
  @body
end

#shaObject (readonly)

Returns the value of attribute sha.



21
22
23
# File 'lib/labkit/redis/script.rb', line 21

def sha
  @sha
end

Instance Method Details

#eval(conn, keys:, argv:) ⇒ Object

Returns the script’s return value.

Parameters:

  • conn

    a Redis client (the connection checked out of a pool)

  • keys (Array)

    KEYS arguments to the Lua script

  • argv (Array)

    ARGV arguments to the Lua script

Returns:

  • the script’s return value



34
35
36
37
38
39
40
# File 'lib/labkit/redis/script.rb', line 34

def eval(conn, keys:, argv:)
  conn.evalsha(@sha, keys: keys, argv: argv)
rescue ::Redis::CommandError => e
  raise unless e.message.start_with?("NOSCRIPT")

  conn.eval(@body, keys: keys, argv: argv)
end