@@ -58,15 +58,10 @@ defmodule BullMQ.RedisConnection do
5858
5959 ## Lua Script Loading
6060
61- BullMQ uses Lua scripts for atomic Redis operations. All scripts are
62- automatically loaded into Redis's script cache when the connection starts.
63- This ensures the connection is fully ready for BullMQ operations (Worker,
64- Queue, QueueEvents, etc.) before it's used.
65-
66- Unlike Node.js BullMQ which uses ioredis's `defineCommand` to register scripts
67- on the client, the Elixir version loads scripts via `SCRIPT LOAD` during
68- initialization and uses `EVALSHA` for execution with automatic `EVAL` fallback
69- on `NOSCRIPT` errors (in case Redis was restarted and lost its script cache).
61+ BullMQ uses Lua scripts for atomic Redis operations. Scripts execute with
62+ `EVALSHA` and lazily fall back to `EVAL` on `NOSCRIPT`, matching the Node.js
63+ ports. For pipelined or transactional paths where that fallback is not
64+ available, BullMQ loads only the specific scripts needed just before use.
7065
7166 ## Options
7267
@@ -112,10 +107,8 @@ defmodule BullMQ.RedisConnection do
112107
113108 case Supervisor . start_link ( __MODULE__ , opts , name: Pool . supervisor_name ( name ) ) do
114109 { :ok , pid } ->
115- # Check Redis version before loading scripts
110+ # Check Redis version before the connection is used
116111 check_redis_version! ( name )
117- # Load scripts synchronously - connection isn't ready until scripts are loaded
118- load_scripts ( name )
119112 { :ok , pid }
120113
121114 error ->
@@ -228,85 +221,6 @@ defmodule BullMQ.RedisConnection do
228221 end
229222 end
230223
231- # Loads all BullMQ Lua scripts into Redis script cache.
232- # Called once during initialization - scripts are cached server-side in Redis,
233- # so all pool connections can use EVALSHA to execute them efficiently.
234- #
235- # To keep startup fast (a cold `SCRIPT LOAD` of many large scripts can be slow
236- # on high-latency links), we first issue a single `SCRIPT EXISTS` call with the
237- # precomputed SHA1 of every script and then only `SCRIPT LOAD` the scripts that
238- # are not already present in the server-side cache.
239- defp load_scripts ( conn ) do
240- scripts =
241- Scripts . list_scripts ( )
242- |> Enum . map ( fn script_name ->
243- case Scripts . get ( script_name ) do
244- { content , _key_count } -> { content , Scripts . get_sha ( script_name ) }
245- nil -> nil
246- end
247- end )
248- |> Enum . reject ( & is_nil / 1 )
249-
250- with { :ok , missing } <- missing_scripts ( conn , scripts ) do
251- load_missing_scripts ( conn , missing )
252- else
253- { :error , reason } ->
254- Logger . warning (
255- "BullMQ: Failed to pre-load scripts for #{ inspect ( conn ) } : #{ inspect ( reason ) } . " <>
256- "Scripts will be loaded on first use via EVAL fallback."
257- )
258-
259- :ok
260- end
261- end
262-
263- # Returns the scripts that are not yet cached server-side, using a single
264- # SCRIPT EXISTS round trip. If any SHA is missing (or the check fails), the
265- # corresponding script is treated as not loaded.
266- defp missing_scripts ( conn , scripts ) do
267- shas = Enum . map ( scripts , fn { _content , sha } -> sha end )
268-
269- case command ( conn , [ "SCRIPT" , "EXISTS" | shas ] ) do
270- { :ok , existing } ->
271- missing =
272- scripts
273- |> Enum . zip ( Stream . concat ( existing , Stream . cycle ( [ 0 ] ) ) )
274- |> Enum . reject ( fn { _script , loaded } -> loaded == 1 end )
275- |> Enum . map ( fn { { content , _sha } , _loaded } -> content end )
276-
277- { :ok , missing }
278-
279- { :error , reason } ->
280- { :error , reason }
281- end
282- end
283-
284- defp load_missing_scripts ( conn , [ ] ) do
285- Logger . debug ( "BullMQ: All Lua scripts already cached in Redis for #{ inspect ( conn ) } " )
286- :ok
287- end
288-
289- defp load_missing_scripts ( conn , missing ) do
290- commands = Enum . map ( missing , fn content -> [ "SCRIPT" , "LOAD" , content ] end )
291-
292- case pipeline ( conn , commands ) do
293- { :ok , _shas } ->
294- Logger . debug (
295- "BullMQ: Loaded #{ length ( commands ) } Lua scripts into Redis cache for #{ inspect ( conn ) } "
296- )
297-
298- :ok
299-
300- { :error , reason } ->
301- Logger . warning (
302- "BullMQ: Failed to pre-load scripts for #{ inspect ( conn ) } : #{ inspect ( reason ) } . " <>
303- "Scripts will be loaded on first use via EVAL fallback."
304- )
305-
306- :ok
307- end
308- end
309-
310224 @ doc """
311225 Executes a Redis command.
312226
0 commit comments