bullpane 0.6.0 → 0.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -16,7 +16,10 @@
16
16
  ARGV[9] byteBudget: stop the call once this many payload bytes were copied
17
17
  into Lua, even if `batch` hashes were not reached. The cursor comes
18
18
  back as usual and the UI keeps streaming.
19
- ARGV[10..] hash fields to HMGET (must include name, data, failedReason)
19
+ ARGV[10] group id (BullMQ Pro), or "" for no group filter
20
+ ARGV[11] the hash fields that may hold the group id, comma separated
21
+ (GROUP_ID_FIELDS in keys.ts); `opts.group.id` is the fallback
22
+ ARGV[12..] hash fields to HMGET (must include name, data, failedReason)
20
23
 
21
24
  Returns { matches, nextCursor, scanned, total, skipped }
22
25
  matches rows shaped exactly like getJobs.lua rows (…, dataTruncated, dataBytes)
@@ -30,6 +33,11 @@
30
33
  call independent of both queue size and payload size: at most `batch` hashes
31
34
  and at most `byteBudget` payload bytes. Before them a search over 1000 × 1 MB
32
35
  jobs kept Redis busy for 13 s; with them a call is a few milliseconds.
36
+
37
+ With a group id, a job outside the group costs one HMGET of its group fields
38
+ and opts (a few hundred bytes, counted in the byte budget) and its payload is
39
+ never read. Pro keeps a group's delayed, failed and completed jobs in the
40
+ queue-wide state keys, so this is the only way to list them per group.
33
41
  ]]
34
42
  local rcall = redis.call
35
43
  local key = KEYS[1]
@@ -42,9 +50,14 @@ local qprefix = ARGV[6]
42
50
  local previewBytes = tonumber(ARGV[7])
43
51
  local maxFieldBytes = tonumber(ARGV[8])
44
52
  local byteBudget = tonumber(ARGV[9])
53
+ local group = ARGV[10]
54
+
55
+ local groupFields = {}
56
+ for f in string.gmatch(ARGV[11], "[^,]+") do groupFields[#groupFields + 1] = f end
57
+ groupFields[#groupFields + 1] = "opts"
45
58
 
46
59
  local fields = {}
47
- for i = 10, #ARGV do fields[#fields + 1] = ARGV[i] end
60
+ for i = 12, #ARGV do fields[#fields + 1] = ARGV[i] end
48
61
  local SKIP = "\0skip"
49
62
 
50
63
  local dataIdx, retIdx, nameIdx, reasonIdx = nil, nil, nil, nil
@@ -83,9 +96,25 @@ local function has(hay, needle)
83
96
  return hay and string.find(string.lower(hay), needle, 1, true) ~= nil
84
97
  end
85
98
 
99
+ -- Exact group match: a group id field on the hash, else opts.group.id. opts is
100
+ -- only decoded when it contains the id as plain text, so most misses cost a find.
101
+ local function inGroup(hkey)
102
+ local vals = rcall("HMGET", hkey, unpack(groupFields))
103
+ local opts = vals[#vals]
104
+ if opts then bytes = bytes + #opts end
105
+ for i = 1, #vals - 1 do
106
+ if vals[i] then return vals[i] == group end
107
+ end
108
+ if not opts or not string.find(opts, group, 1, true) then return false end
109
+ local ok, decoded = pcall(cjson.decode, opts)
110
+ if not ok or type(decoded) ~= "table" or type(decoded.group) ~= "table" then return false end
111
+ local id = decoded.group.id
112
+ return id ~= nil and tostring(id) == group
113
+ end
114
+
86
115
  for _, id in ipairs(ids) do
87
116
  scanned = scanned + 1
88
- if string.sub(id, 1, 2) ~= "0:" then
117
+ if string.sub(id, 1, 2) ~= "0:" and (group == "" or inGroup(qprefix .. id)) then
89
118
  local hkey = qprefix .. id
90
119
  local dataBytes = dataIdx and rcall("HSTRLEN", hkey, "data") or 0
91
120
  local retBytes = retIdx and rcall("HSTRLEN", hkey, "returnvalue") or 0
@@ -129,12 +158,13 @@ for _, id in ipairs(ids) do
129
158
  break
130
159
  end
131
160
  end
132
- if bytes >= byteBudget then
133
- stoppedEarly = true
134
- break
135
- end
136
161
  end
137
162
  end
163
+ -- Also after a group miss: those read opts, which counts against the budget.
164
+ if bytes >= byteBudget then
165
+ stoppedEarly = true
166
+ break
167
+ end
138
168
  end
139
169
 
140
170
  local nextCursor = cursor + scanned