Module: Wurk::Lua::FastDelete
- Defined in:
- lib/wurk/lua/fast_delete.rb
Overview
Pro Fast API (ยง11) deletes, Queue#delete_job and #delete_by_class: a
cursor walk over the queue list from the head, one fast_delete_window
call per WINDOW entries. The scripts this replaced copied the whole list
into the Lua heap and LREMed per match, holding Redis for the entire
queue (~300ms per call at 100k jobs).
Each call is atomic and removes only payloads it matched, so nothing that did not match is ever deleted. Between calls the list moves:
* pops from the tail (every fetcher: LMOVE/BLMOVE RIGHT, BRPOP) shift no
head index, so they cannot make the walk skip an entry;
* pushes at the head (LPUSH, every enqueue) shift entries already
visited forward, into a window still to come: they are read again,
which re-checks a non-match and costs nothing else;
* the walk's own removals are subtracted from the cursor.
What can make it miss a match is another removal ahead of the cursor between calls (a concurrent delete on the same queue, an LREM or LPOP by another client): the entries shift back past the cursor. Such a match stays in the queue and a second call finds it; nothing extra is ever removed.
Constant Summary collapse
- WINDOW =
1000- MAX_REMOVED_PER_CALL =
Matches one call rewrites before it hands the cursor on: each is an LSET that walks the list to its index (see fast_delete_window.lua).
100- TOMBSTONE =
No JSON payload starts with a NUL byte.
"\0wurk-fast-delete\0"
Class Method Summary collapse
-
.call(conn, key, needle, window: WINDOW, max_removed: MAX_REMOVED_PER_CALL) ⇒ Object
[payloads removed, first removed payload or nil].
- .delete_by_class(conn, key, klass) ⇒ Object
- .delete_job(conn, key, jid) ⇒ Object
Class Method Details
.call(conn, key, needle, window: WINDOW, max_removed: MAX_REMOVED_PER_CALL) ⇒ Object
[payloads removed, first removed payload or nil].
36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/wurk/lua/fast_delete.rb', line 36 def call(conn, key, needle, window: WINDOW, max_removed: MAX_REMOVED_PER_CALL) cursor = 0 removed = 0 first = nil loop do argv = [needle, cursor, window, TOMBSTONE, max_removed] cursor, count, payload = Loader.eval_cached(conn, :fast_delete_window, keys: [key], argv: argv) removed += count first ||= payload return [removed, first] if cursor.negative? end end |
.delete_by_class(conn, key, klass) ⇒ Object
53 54 55 |
# File 'lib/wurk/lua/fast_delete.rb', line 53 def delete_by_class(conn, key, klass) call(conn, key, %("class":"#{klass}")).first end |
.delete_job(conn, key, jid) ⇒ Object
49 50 51 |
# File 'lib/wurk/lua/fast_delete.rb', line 49 def delete_job(conn, key, jid) call(conn, key, %("jid":"#{jid}")).last end |