jonnify·redis /redis-patterns/caching/client-side-caching/script-cache
Redis Patterns / R1 · Caching / Client-side caching / The SHA1 script-cache parallel

R1.04.3 · Client-side caching — dive 3

The SHA1 script-cache parallel.

Run a Lua script by its hash, not its source — and on a cache-miss reply, send the source once. The same cache-then-invalidate shape, in real EchoMQ code.

Grounding: echo_wire/script.ex (EchoMQ.Script.new/2, EVALSHA-first) · echo_store/coherence.ex (the worked @drop = Script.new) — shown as a parallel, not a door.

Run a script. Hit by hash, or miss and resend — select a scenario, or hover a node.
the connector EchoMQ.Connector.eval Valkey script cache (SHA1) EVALSHA <sha1> result — run by hash; resend the source only on a miss
readout · Select a scenario.
§1

Run by hash, resend on miss

source · the cache-then-invalidate shape

Loading a script with SCRIPT LOAD registers its body in the server's script cache and returns its SHA1. From then on a client runs it with EVALSHA — sending the 40-character hex hash, not the script text. The body travels the wire once; every later run is a hash. The hit case is a pure win: less data sent, no parse.

The miss case is the half that makes the parallel exact. If the server has dropped the script — a restart, a SCRIPT FLUSH, an unseen replica — EVALSHA returns a NOSCRIPT error. That error is the invalidation: the client's assumption that the server holds the script is wrong, so the client falls back to EVAL, sending the full source, which re-registers the hash. One miss, one resend, then hits again. A near cache drops a value on a broadcast push; a script cache resends a body on a NOSCRIPT. The signal differs; the shape is the same.

EVALSHA
Run a server-cached script by its SHA1 hash; the body is not sent.
NOSCRIPT
The reply when the server does not hold that hash — the cache-miss signal.
EVAL
The fallback: send the full source, run it, and re-register the hash for next time.
SHA1
The content hash that names a script; the cache key on both sides.
§2

In EchoMQ.Script

echo_wire/script.ex · verbatim

EchoMQ runs its state transitions as Lua, so the same scripts run constantly — which is exactly the case the SHA1 cache is for. The real type is EchoMQ.Script in echo/apps/echo_wire/lib/echo_mq/script.ex. It is a tiny struct that precomputes the SHA1 at definition time — the cache key is derived once, not on every call — so the connector can run EVALSHA-first with a load-on-NOSCRIPT fallback:

echo/apps/echo_wire/lib/echo_mq/script.ex · the SHA1 cached client-sidefrozen
defmodule EchoMQ.Script do
  @moduledoc """
  A server-side script with its SHA1 precomputed, so the connector can run
  EVALSHA-first with a load-on-NOSCRIPT fallback. ...
  """
  defstruct [:name, :source, :sha]

  def new(name, source) when is_atom(name) and is_binary(source) do
    sha = :crypto.hash(:sha, source) |> Base.encode16(case: :lower)
    %__MODULE__{name: name, source: source, sha: sha}
  end
end

The worked example sits in EchoStore itself: the version-safe L2 drop is a module attribute, defined once with its SHA1 already computed, then dispatched by hash through the connector's eval:

# echo/apps/echo_store/lib/echo_store/coherence.ex — the cache key minted once
@drop Script.new(:coherence_drop, """
      local cur = redis.call('GET', KEYS[1])
      if not cur then return 0 end
      ...
      """)

def drop_l2(conn, table, id, version) do
  Connector.eval(conn, @drop, [Keyspace.key(table, id)], [version])   # EVALSHA-first
end

Notes on ValkeyEVALSHA runs a script the server already holds by hash; a NOSCRIPT reply is the only miss, and the client loads the source once on it. The committed connector record shows the discipline at work: script_loads=1 — exactly one load per script per connection — valkey.io/topics/programmability.

§3

The same pattern, mapped

near cache → script cache

Set the two side by side. Each role is one part of the near-cache pattern and its counterpart in EchoMQ.Script. Pick a role to read both sides at once; the cache-then-invalidate shape is the same down every row.

Map a role. Near cache to script cache.
readout · Pick a role to read both sides at once.
cross-course · /echomq

The EVALSHA-first protocol, in depth

The SHA1 cache is the client-side-caching idea applied to scripts — but the full story behind EchoMQ.Script (the whole Lua bundle, the version fence, the protocol governance) is a course of its own. This dive draws the parallel; the EchoMQ course teaches the protocol.

/echomq/cache — EchoStore, in depth →

client-side caching

Hold a value locally; read it from memory. On a change, a broadcast push drops the copy, and the next read fetches once and re-caches.

EchoMQ.Script

Hold a script's precomputed SHA1; run it by hash with eval. On a NOSCRIPT reply the assumption is dropped, and the connector resends the full source once — the real Script.new/2.

Cache a derived thing near the work; take a signal that it is gone, and refill once. The near cache and EchoMQ.Script are the same pattern with different cargo.

§4

References

sources · related

Sources

Related in this course