bunqueue 1.9.7 → 1.9.9

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.
Files changed (245) hide show
  1. package/dist/application/backgroundTasks.d.ts +3 -6
  2. package/dist/application/backgroundTasks.d.ts.map +1 -1
  3. package/dist/application/backgroundTasks.js +10 -179
  4. package/dist/application/backgroundTasks.js.map +1 -1
  5. package/dist/application/cleanupTasks.d.ts +1 -1
  6. package/dist/application/cleanupTasks.d.ts.map +1 -1
  7. package/dist/application/cleanupTasks.js +61 -22
  8. package/dist/application/cleanupTasks.js.map +1 -1
  9. package/dist/application/clientTracking.d.ts +22 -0
  10. package/dist/application/clientTracking.d.ts.map +1 -0
  11. package/dist/application/clientTracking.js +118 -0
  12. package/dist/application/clientTracking.js.map +1 -0
  13. package/dist/application/contextFactory.d.ts +97 -0
  14. package/dist/application/contextFactory.d.ts.map +1 -0
  15. package/dist/application/contextFactory.js +170 -0
  16. package/dist/application/contextFactory.js.map +1 -0
  17. package/dist/application/dependencyProcessor.d.ts +11 -0
  18. package/dist/application/dependencyProcessor.d.ts.map +1 -0
  19. package/dist/application/dependencyProcessor.js +69 -0
  20. package/dist/application/dependencyProcessor.js.map +1 -0
  21. package/dist/application/dlqManager.d.ts +12 -0
  22. package/dist/application/dlqManager.d.ts.map +1 -1
  23. package/dist/application/dlqManager.js +36 -0
  24. package/dist/application/dlqManager.js.map +1 -1
  25. package/dist/application/lockManager.d.ts +3 -49
  26. package/dist/application/lockManager.d.ts.map +1 -1
  27. package/dist/application/lockManager.js +101 -272
  28. package/dist/application/lockManager.js.map +1 -1
  29. package/dist/application/lockOperations.d.ts +39 -0
  30. package/dist/application/lockOperations.d.ts.map +1 -0
  31. package/dist/application/lockOperations.js +101 -0
  32. package/dist/application/lockOperations.js.map +1 -0
  33. package/dist/application/operations/ack.d.ts +1 -5
  34. package/dist/application/operations/ack.d.ts.map +1 -1
  35. package/dist/application/operations/ack.js +43 -259
  36. package/dist/application/operations/ack.js.map +1 -1
  37. package/dist/application/operations/ackHelpers.d.ts +79 -0
  38. package/dist/application/operations/ackHelpers.d.ts.map +1 -0
  39. package/dist/application/operations/ackHelpers.js +173 -0
  40. package/dist/application/operations/ackHelpers.js.map +1 -0
  41. package/dist/application/operations/jobManagement.d.ts +2 -0
  42. package/dist/application/operations/jobManagement.d.ts.map +1 -1
  43. package/dist/application/operations/jobManagement.js +8 -0
  44. package/dist/application/operations/jobManagement.js.map +1 -1
  45. package/dist/application/operations/push.d.ts.map +1 -1
  46. package/dist/application/operations/push.js +20 -6
  47. package/dist/application/operations/push.js.map +1 -1
  48. package/dist/application/operations/queryOperations.d.ts +11 -0
  49. package/dist/application/operations/queryOperations.d.ts.map +1 -1
  50. package/dist/application/operations/queryOperations.js +32 -0
  51. package/dist/application/operations/queryOperations.js.map +1 -1
  52. package/dist/application/queueManager.d.ts +3 -11
  53. package/dist/application/queueManager.d.ts.map +1 -1
  54. package/dist/application/queueManager.js +98 -244
  55. package/dist/application/queueManager.js.map +1 -1
  56. package/dist/application/stallDetection.d.ts +11 -0
  57. package/dist/application/stallDetection.d.ts.map +1 -0
  58. package/dist/application/stallDetection.js +128 -0
  59. package/dist/application/stallDetection.js.map +1 -0
  60. package/dist/application/types.js +1 -1
  61. package/dist/application/types.js.map +1 -1
  62. package/dist/cli/client.d.ts +3 -5
  63. package/dist/cli/client.d.ts.map +1 -1
  64. package/dist/cli/client.js +31 -27
  65. package/dist/cli/client.js.map +1 -1
  66. package/dist/cli/commands/core.js +3 -3
  67. package/dist/cli/commands/core.js.map +1 -1
  68. package/dist/cli/commands/job.js +14 -14
  69. package/dist/cli/commands/job.js.map +1 -1
  70. package/dist/cli/commands/server.d.ts.map +1 -1
  71. package/dist/cli/commands/server.js +5 -29
  72. package/dist/cli/commands/server.js.map +1 -1
  73. package/dist/cli/index.d.ts.map +1 -1
  74. package/dist/cli/index.js +1 -9
  75. package/dist/cli/index.js.map +1 -1
  76. package/dist/client/events.d.ts +0 -1
  77. package/dist/client/events.d.ts.map +1 -1
  78. package/dist/client/events.js +4 -7
  79. package/dist/client/events.js.map +1 -1
  80. package/dist/client/flow.d.ts +23 -1
  81. package/dist/client/flow.d.ts.map +1 -1
  82. package/dist/client/flow.js +166 -68
  83. package/dist/client/flow.js.map +1 -1
  84. package/dist/client/queue/queue.d.ts.map +1 -1
  85. package/dist/client/queue/queue.js +3 -1
  86. package/dist/client/queue/queue.js.map +1 -1
  87. package/dist/client/sandboxed/types.d.ts +1 -0
  88. package/dist/client/sandboxed/types.d.ts.map +1 -1
  89. package/dist/client/sandboxed/worker.d.ts +1 -0
  90. package/dist/client/sandboxed/worker.d.ts.map +1 -1
  91. package/dist/client/sandboxed/worker.js +31 -8
  92. package/dist/client/sandboxed/worker.js.map +1 -1
  93. package/dist/client/sandboxed/wrapper.d.ts.map +1 -1
  94. package/dist/client/sandboxed/wrapper.js +10 -1
  95. package/dist/client/sandboxed/wrapper.js.map +1 -1
  96. package/dist/client/tcp/client.d.ts +4 -1
  97. package/dist/client/tcp/client.d.ts.map +1 -1
  98. package/dist/client/tcp/client.js +26 -8
  99. package/dist/client/tcp/client.js.map +1 -1
  100. package/dist/client/tcp/connection.d.ts +6 -8
  101. package/dist/client/tcp/connection.d.ts.map +1 -1
  102. package/dist/client/tcp/connection.js +24 -22
  103. package/dist/client/tcp/connection.js.map +1 -1
  104. package/dist/client/tcp/index.d.ts +0 -1
  105. package/dist/client/tcp/index.d.ts.map +1 -1
  106. package/dist/client/tcp/index.js +0 -1
  107. package/dist/client/tcp/index.js.map +1 -1
  108. package/dist/client/tcp/types.d.ts +8 -13
  109. package/dist/client/tcp/types.d.ts.map +1 -1
  110. package/dist/client/tcp/types.js +0 -1
  111. package/dist/client/tcp/types.js.map +1 -1
  112. package/dist/client/tcpPool.d.ts.map +1 -1
  113. package/dist/client/tcpPool.js +0 -6
  114. package/dist/client/tcpPool.js.map +1 -1
  115. package/dist/client/worker/ackBatcher.d.ts +1 -1
  116. package/dist/client/worker/ackBatcher.d.ts.map +1 -1
  117. package/dist/client/worker/ackBatcher.js +20 -18
  118. package/dist/client/worker/ackBatcher.js.map +1 -1
  119. package/dist/client/worker/jobParser.d.ts.map +1 -1
  120. package/dist/client/worker/jobParser.js +8 -7
  121. package/dist/client/worker/jobParser.js.map +1 -1
  122. package/dist/client/worker/processor.d.ts.map +1 -1
  123. package/dist/client/worker/processor.js +10 -6
  124. package/dist/client/worker/processor.js.map +1 -1
  125. package/dist/domain/queue/dependencyTracker.d.ts +74 -0
  126. package/dist/domain/queue/dependencyTracker.d.ts.map +1 -0
  127. package/dist/domain/queue/dependencyTracker.js +126 -0
  128. package/dist/domain/queue/dependencyTracker.js.map +1 -0
  129. package/dist/domain/queue/dlqShard.d.ts +61 -0
  130. package/dist/domain/queue/dlqShard.d.ts.map +1 -0
  131. package/dist/domain/queue/dlqShard.js +175 -0
  132. package/dist/domain/queue/dlqShard.js.map +1 -0
  133. package/dist/domain/queue/limiterManager.d.ts +44 -0
  134. package/dist/domain/queue/limiterManager.d.ts.map +1 -0
  135. package/dist/domain/queue/limiterManager.js +99 -0
  136. package/dist/domain/queue/limiterManager.js.map +1 -0
  137. package/dist/domain/queue/shard.d.ts +33 -124
  138. package/dist/domain/queue/shard.d.ts.map +1 -1
  139. package/dist/domain/queue/shard.js +157 -427
  140. package/dist/domain/queue/shard.js.map +1 -1
  141. package/dist/domain/queue/temporalManager.d.ts +82 -0
  142. package/dist/domain/queue/temporalManager.d.ts.map +1 -0
  143. package/dist/domain/queue/temporalManager.js +150 -0
  144. package/dist/domain/queue/temporalManager.js.map +1 -0
  145. package/dist/domain/queue/uniqueKeyManager.d.ts +32 -0
  146. package/dist/domain/queue/uniqueKeyManager.d.ts.map +1 -0
  147. package/dist/domain/queue/uniqueKeyManager.js +87 -0
  148. package/dist/domain/queue/uniqueKeyManager.js.map +1 -0
  149. package/dist/domain/types/command.d.ts +6 -0
  150. package/dist/domain/types/command.d.ts.map +1 -1
  151. package/dist/infrastructure/backup/s3Backup.d.ts +3 -40
  152. package/dist/infrastructure/backup/s3Backup.d.ts.map +1 -1
  153. package/dist/infrastructure/backup/s3Backup.js +10 -182
  154. package/dist/infrastructure/backup/s3Backup.js.map +1 -1
  155. package/dist/infrastructure/backup/s3BackupConfig.d.ts +67 -0
  156. package/dist/infrastructure/backup/s3BackupConfig.d.ts.map +1 -0
  157. package/dist/infrastructure/backup/s3BackupConfig.js +48 -0
  158. package/dist/infrastructure/backup/s3BackupConfig.js.map +1 -0
  159. package/dist/infrastructure/backup/s3BackupOperations.d.ts +23 -0
  160. package/dist/infrastructure/backup/s3BackupOperations.d.ts.map +1 -0
  161. package/dist/infrastructure/backup/s3BackupOperations.js +170 -0
  162. package/dist/infrastructure/backup/s3BackupOperations.js.map +1 -0
  163. package/dist/infrastructure/persistence/sqlite.d.ts +6 -13
  164. package/dist/infrastructure/persistence/sqlite.d.ts.map +1 -1
  165. package/dist/infrastructure/persistence/sqlite.js +28 -179
  166. package/dist/infrastructure/persistence/sqlite.js.map +1 -1
  167. package/dist/infrastructure/persistence/sqliteBatch.d.ts +38 -0
  168. package/dist/infrastructure/persistence/sqliteBatch.d.ts.map +1 -0
  169. package/dist/infrastructure/persistence/sqliteBatch.js +124 -0
  170. package/dist/infrastructure/persistence/sqliteBatch.js.map +1 -0
  171. package/dist/infrastructure/persistence/sqliteSerializer.d.ts +17 -0
  172. package/dist/infrastructure/persistence/sqliteSerializer.d.ts.map +1 -0
  173. package/dist/infrastructure/persistence/sqliteSerializer.js +81 -0
  174. package/dist/infrastructure/persistence/sqliteSerializer.js.map +1 -0
  175. package/dist/infrastructure/persistence/statements.d.ts +1 -1
  176. package/dist/infrastructure/persistence/statements.d.ts.map +1 -1
  177. package/dist/infrastructure/persistence/statements.js +3 -2
  178. package/dist/infrastructure/persistence/statements.js.map +1 -1
  179. package/dist/infrastructure/scheduler/cronScheduler.d.ts +7 -0
  180. package/dist/infrastructure/scheduler/cronScheduler.d.ts.map +1 -1
  181. package/dist/infrastructure/scheduler/cronScheduler.js +23 -3
  182. package/dist/infrastructure/scheduler/cronScheduler.js.map +1 -1
  183. package/dist/infrastructure/server/handler.d.ts.map +1 -1
  184. package/dist/infrastructure/server/handler.js +1 -186
  185. package/dist/infrastructure/server/handler.js.map +1 -1
  186. package/dist/infrastructure/server/handlerRoutes.d.ts +23 -0
  187. package/dist/infrastructure/server/handlerRoutes.d.ts.map +1 -0
  188. package/dist/infrastructure/server/handlerRoutes.js +190 -0
  189. package/dist/infrastructure/server/handlerRoutes.js.map +1 -0
  190. package/dist/infrastructure/server/handlers/core.d.ts.map +1 -1
  191. package/dist/infrastructure/server/handlers/core.js +26 -19
  192. package/dist/infrastructure/server/handlers/core.js.map +1 -1
  193. package/dist/infrastructure/server/http.d.ts +4 -25
  194. package/dist/infrastructure/server/http.d.ts.map +1 -1
  195. package/dist/infrastructure/server/http.js +68 -285
  196. package/dist/infrastructure/server/http.js.map +1 -1
  197. package/dist/infrastructure/server/httpEndpoints.d.ts +19 -0
  198. package/dist/infrastructure/server/httpEndpoints.d.ts.map +1 -0
  199. package/dist/infrastructure/server/httpEndpoints.js +151 -0
  200. package/dist/infrastructure/server/httpEndpoints.js.map +1 -0
  201. package/dist/infrastructure/server/protocol.d.ts +15 -1
  202. package/dist/infrastructure/server/protocol.d.ts.map +1 -1
  203. package/dist/infrastructure/server/protocol.js +37 -3
  204. package/dist/infrastructure/server/protocol.js.map +1 -1
  205. package/dist/infrastructure/server/sseHandler.d.ts +27 -0
  206. package/dist/infrastructure/server/sseHandler.d.ts.map +1 -0
  207. package/dist/infrastructure/server/sseHandler.js +77 -0
  208. package/dist/infrastructure/server/sseHandler.js.map +1 -0
  209. package/dist/infrastructure/server/tcp.d.ts +8 -10
  210. package/dist/infrastructure/server/tcp.d.ts.map +1 -1
  211. package/dist/infrastructure/server/tcp.js +51 -42
  212. package/dist/infrastructure/server/tcp.js.map +1 -1
  213. package/dist/infrastructure/server/wsHandler.d.ts +31 -0
  214. package/dist/infrastructure/server/wsHandler.d.ts.map +1 -0
  215. package/dist/infrastructure/server/wsHandler.js +63 -0
  216. package/dist/infrastructure/server/wsHandler.js.map +1 -0
  217. package/dist/main.js +2 -4
  218. package/dist/main.js.map +1 -1
  219. package/dist/mcp/index.js +3 -465
  220. package/dist/mcp/index.js.map +1 -1
  221. package/dist/mcp/mcpHandlers.d.ts +129 -0
  222. package/dist/mcp/mcpHandlers.d.ts.map +1 -0
  223. package/dist/mcp/mcpHandlers.js +204 -0
  224. package/dist/mcp/mcpHandlers.js.map +1 -0
  225. package/dist/mcp/mcpTools.d.ts +15 -0
  226. package/dist/mcp/mcpTools.d.ts.map +1 -0
  227. package/dist/mcp/mcpTools.js +277 -0
  228. package/dist/mcp/mcpTools.js.map +1 -0
  229. package/dist/shared/lru.d.ts +23 -0
  230. package/dist/shared/lru.d.ts.map +1 -1
  231. package/dist/shared/lru.js +61 -3
  232. package/dist/shared/lru.js.map +1 -1
  233. package/dist/shared/skipList.d.ts +10 -2
  234. package/dist/shared/skipList.d.ts.map +1 -1
  235. package/dist/shared/skipList.js +22 -1
  236. package/dist/shared/skipList.js.map +1 -1
  237. package/package.json +2 -2
  238. package/dist/cli/dashboard.d.ts +0 -32
  239. package/dist/cli/dashboard.d.ts.map +0 -1
  240. package/dist/cli/dashboard.js +0 -183
  241. package/dist/cli/dashboard.js.map +0 -1
  242. package/dist/client/tcp/lineBuffer.d.ts +0 -17
  243. package/dist/client/tcp/lineBuffer.d.ts.map +0 -1
  244. package/dist/client/tcp/lineBuffer.js +0 -32
  245. package/dist/client/tcp/lineBuffer.js.map +0 -1
@@ -13,7 +13,7 @@ import { RWLock } from '../shared/lock';
13
13
  import { shardIndex, SHARD_COUNT } from '../shared/hash';
14
14
  import { pushJob, pushJobBatch } from './operations/push';
15
15
  import { pullJob, pullJobBatch } from './operations/pull';
16
- import { ackJob, ackJobBatch, ackJobBatchWithResults, failJob, } from './operations/ack';
16
+ import { ackJob, ackJobBatch, ackJobBatchWithResults, failJob } from './operations/ack';
17
17
  import * as queueControl from './operations/queueControl';
18
18
  import * as jobMgmt from './operations/jobManagement';
19
19
  import * as queryOps from './operations/queryOperations';
@@ -25,6 +25,7 @@ import { DEFAULT_CONFIG } from './types';
25
25
  import * as lockMgr from './lockManager';
26
26
  import * as bgTasks from './backgroundTasks';
27
27
  import * as statsMgr from './statsManager';
28
+ import { ContextFactory } from './contextFactory';
28
29
  /**
29
30
  * QueueManager - Central coordinator
30
31
  */
@@ -46,7 +47,7 @@ export class QueueManager {
46
47
  pendingDepChecks = new Set();
47
48
  // Two-phase stall detection
48
49
  stalledCandidates = new Set();
49
- // Lock-based job ownership tracking (BullMQ-style)
50
+ // Lock-based job ownership tracking
50
51
  jobLocks = new Map();
51
52
  clientJobs = new Map();
52
53
  // Cron scheduler
@@ -66,9 +67,11 @@ export class QueueManager {
66
67
  };
67
68
  startTime = Date.now();
68
69
  // Background task handles
69
- backgroundTaskHandles = null;
70
- // Queue names cache for O(1) listQueues
70
+ backgroundTaskHandles;
71
+ // Queue names cache
71
72
  queueNamesCache = new Set();
73
+ // Context factory
74
+ contextFactory;
72
75
  constructor(config = {}) {
73
76
  this.config = { ...DEFAULT_CONFIG, ...config };
74
77
  this.storage = config.dataPath ? new SqliteStorage({ path: config.dataPath }) : null;
@@ -91,32 +94,28 @@ export class QueueManager {
91
94
  this.cronScheduler.setPushCallback(async (queue, input) => {
92
95
  await this.push(queue, input);
93
96
  });
97
+ // Set up persistence callback for cron state
98
+ if (this.storage) {
99
+ const storage = this.storage;
100
+ this.cronScheduler.setPersistCallback((name, executions, nextRun) => {
101
+ storage.updateCron(name, executions, nextRun);
102
+ });
103
+ }
94
104
  // Initialize managers
95
105
  this.webhookManager = new WebhookManager();
96
106
  this.workerManager = new WorkerManager();
97
107
  this.eventsManager = new EventsManager(this.webhookManager);
108
+ // Initialize context factory
109
+ this.contextFactory = new ContextFactory(this.getContextDependencies(), this.getContextCallbacks());
98
110
  // Load and start
99
- bgTasks.recover(this.getBackgroundContext());
100
- // Load cron jobs from storage
111
+ bgTasks.recover(this.contextFactory.getBackgroundContext());
101
112
  if (this.storage) {
102
113
  this.cronScheduler.load(this.storage.loadCronJobs());
103
114
  }
104
- this.backgroundTaskHandles = bgTasks.startBackgroundTasks(this.getBackgroundContext(), this.cronScheduler);
105
- }
106
- // ============ Context Builders ============
107
- getLockContext() {
108
- return {
109
- jobIndex: this.jobIndex,
110
- jobLocks: this.jobLocks,
111
- clientJobs: this.clientJobs,
112
- processingShards: this.processingShards,
113
- processingLocks: this.processingLocks,
114
- shards: this.shards,
115
- shardLocks: this.shardLocks,
116
- eventsManager: this.eventsManager,
117
- };
115
+ this.backgroundTaskHandles = bgTasks.startBackgroundTasks(this.contextFactory.getBackgroundContext(), this.cronScheduler);
118
116
  }
119
- getBackgroundContext() {
117
+ // ============ Context Dependencies ============
118
+ getContextDependencies() {
120
119
  return {
121
120
  config: this.config,
122
121
  storage: this.storage,
@@ -138,68 +137,16 @@ export class QueueManager {
138
137
  webhookManager: this.webhookManager,
139
138
  metrics: this.metrics,
140
139
  startTime: this.startTime,
141
- fail: this.fail.bind(this),
142
- registerQueueName: this.registerQueueName.bind(this),
143
- unregisterQueueName: this.unregisterQueueName.bind(this),
144
- };
145
- }
146
- getStatsContext() {
147
- return {
148
- shards: this.shards,
149
- processingShards: this.processingShards,
150
- completedJobs: this.completedJobs,
151
- jobIndex: this.jobIndex,
152
- jobResults: this.jobResults,
153
- jobLogs: this.jobLogs,
154
- customIdMap: this.customIdMap,
155
- jobLocks: this.jobLocks,
156
- clientJobs: this.clientJobs,
157
- pendingDepChecks: this.pendingDepChecks,
158
- stalledCandidates: this.stalledCandidates,
159
- metrics: this.metrics,
160
- startTime: this.startTime,
161
- };
162
- }
163
- getPushContext() {
164
- return {
165
- storage: this.storage,
166
- shards: this.shards,
167
- shardLocks: this.shardLocks,
168
- completedJobs: this.completedJobs,
169
- customIdMap: this.customIdMap,
170
- jobIndex: this.jobIndex,
171
- totalPushed: this.metrics.totalPushed,
172
- broadcast: this.eventsManager.broadcast.bind(this.eventsManager),
173
- };
174
- }
175
- getPullContext() {
176
- return {
177
- storage: this.storage,
178
- shards: this.shards,
179
- shardLocks: this.shardLocks,
180
- processingShards: this.processingShards,
181
- processingLocks: this.processingLocks,
182
- jobIndex: this.jobIndex,
183
- totalPulled: this.metrics.totalPulled,
184
- broadcast: this.eventsManager.broadcast.bind(this.eventsManager),
140
+ maxLogsPerJob: this.maxLogsPerJob,
185
141
  };
186
142
  }
187
- getAckContext() {
143
+ getContextCallbacks() {
188
144
  return {
189
- storage: this.storage,
190
- shards: this.shards,
191
- shardLocks: this.shardLocks,
192
- processingShards: this.processingShards,
193
- processingLocks: this.processingLocks,
194
- completedJobs: this.completedJobs,
195
- jobResults: this.jobResults,
196
- jobIndex: this.jobIndex,
197
- totalCompleted: this.metrics.totalCompleted,
198
- totalFailed: this.metrics.totalFailed,
199
- broadcast: this.eventsManager.broadcast.bind(this.eventsManager),
145
+ fail: this.fail.bind(this),
146
+ registerQueueName: this.registerQueueName.bind(this),
147
+ unregisterQueueName: this.unregisterQueueName.bind(this),
200
148
  onJobCompleted: this.onJobCompleted.bind(this),
201
149
  onJobsCompleted: this.onJobsCompleted.bind(this),
202
- needsBroadcast: this.eventsManager.needsBroadcast.bind(this.eventsManager),
203
150
  hasPendingDeps: this.hasPendingDeps.bind(this),
204
151
  onRepeat: this.handleRepeat.bind(this),
205
152
  };
@@ -229,115 +176,87 @@ export class QueueManager {
229
176
  },
230
177
  });
231
178
  }
232
- getJobMgmtContext() {
233
- return {
234
- storage: this.storage,
235
- shards: this.shards,
236
- shardLocks: this.shardLocks,
237
- processingShards: this.processingShards,
238
- processingLocks: this.processingLocks,
239
- jobIndex: this.jobIndex,
240
- webhookManager: this.webhookManager,
241
- };
242
- }
243
- getQueryContext() {
244
- return {
245
- storage: this.storage,
246
- shards: this.shards,
247
- shardLocks: this.shardLocks,
248
- processingShards: this.processingShards,
249
- processingLocks: this.processingLocks,
250
- jobIndex: this.jobIndex,
251
- completedJobs: this.completedJobs,
252
- jobResults: this.jobResults,
253
- customIdMap: this.customIdMap,
254
- };
255
- }
256
- getDlqContext() {
257
- return {
258
- shards: this.shards,
259
- jobIndex: this.jobIndex,
260
- storage: this.storage,
261
- };
262
- }
263
179
  // ============ Core Operations ============
264
180
  async push(queue, input) {
265
181
  this.registerQueueName(queue);
266
- return pushJob(queue, input, this.getPushContext());
182
+ return pushJob(queue, input, this.contextFactory.getPushContext());
267
183
  }
268
184
  async pushBatch(queue, inputs) {
269
185
  this.registerQueueName(queue);
270
- return pushJobBatch(queue, inputs, this.getPushContext());
186
+ return pushJobBatch(queue, inputs, this.contextFactory.getPushContext());
271
187
  }
272
188
  async pull(queue, timeoutMs = 0) {
273
- return pullJob(queue, timeoutMs, this.getPullContext());
189
+ return pullJob(queue, timeoutMs, this.contextFactory.getPullContext());
274
190
  }
275
191
  async pullWithLock(queue, owner, timeoutMs = 0, lockTtl = DEFAULT_LOCK_TTL) {
276
- const job = await pullJob(queue, timeoutMs, this.getPullContext());
192
+ const job = await pullJob(queue, timeoutMs, this.contextFactory.getPullContext());
277
193
  if (!job)
278
194
  return { job: null, token: null };
279
- const token = lockMgr.createLock(job.id, owner, this.getLockContext(), lockTtl);
195
+ const token = lockMgr.createLock(job.id, owner, this.contextFactory.getLockContext(), lockTtl);
280
196
  return { job, token };
281
197
  }
282
198
  async pullBatch(queue, count, timeoutMs = 0) {
283
- return pullJobBatch(queue, count, timeoutMs, this.getPullContext());
199
+ return pullJobBatch(queue, count, timeoutMs, this.contextFactory.getPullContext());
284
200
  }
285
201
  async pullBatchWithLock(queue, count, owner, timeoutMs = 0, lockTtl = DEFAULT_LOCK_TTL) {
286
- const jobs = await pullJobBatch(queue, count, timeoutMs, this.getPullContext());
202
+ const jobs = await pullJobBatch(queue, count, timeoutMs, this.contextFactory.getPullContext());
287
203
  const tokens = [];
288
204
  for (const job of jobs) {
289
- const token = lockMgr.createLock(job.id, owner, this.getLockContext(), lockTtl);
205
+ const token = lockMgr.createLock(job.id, owner, this.contextFactory.getLockContext(), lockTtl);
290
206
  tokens.push(token ?? '');
291
207
  }
292
208
  return { jobs, tokens };
293
209
  }
294
210
  async ack(jobId, result, token) {
295
- if (token && !lockMgr.verifyLock(jobId, token, this.getLockContext())) {
211
+ if (token && !lockMgr.verifyLock(jobId, token, this.contextFactory.getLockContext())) {
296
212
  throw new Error(`Invalid or expired lock token for job ${jobId}`);
297
213
  }
298
- await ackJob(jobId, result, this.getAckContext());
299
- lockMgr.releaseLock(jobId, this.getLockContext(), token);
214
+ await ackJob(jobId, result, this.contextFactory.getAckContext());
215
+ lockMgr.releaseLock(jobId, this.contextFactory.getLockContext(), token);
300
216
  }
301
217
  async ackBatch(jobIds, tokens) {
218
+ const lockCtx = this.contextFactory.getLockContext();
302
219
  if (tokens?.length === jobIds.length) {
303
220
  for (let i = 0; i < jobIds.length; i++) {
304
221
  const t = tokens[i];
305
- if (t && !lockMgr.verifyLock(jobIds[i], t, this.getLockContext())) {
222
+ if (t && !lockMgr.verifyLock(jobIds[i], t, lockCtx)) {
306
223
  throw new Error(`Invalid or expired lock token for job ${jobIds[i]}`);
307
224
  }
308
225
  }
309
226
  }
310
- await ackJobBatch(jobIds, this.getAckContext());
227
+ await ackJobBatch(jobIds, this.contextFactory.getAckContext());
311
228
  if (tokens) {
312
229
  for (let i = 0; i < jobIds.length; i++) {
313
- lockMgr.releaseLock(jobIds[i], this.getLockContext(), tokens[i]);
230
+ lockMgr.releaseLock(jobIds[i], lockCtx, tokens[i]);
314
231
  }
315
232
  }
316
233
  }
317
234
  async ackBatchWithResults(items) {
235
+ const lockCtx = this.contextFactory.getLockContext();
318
236
  for (const item of items) {
319
- if (item.token && !lockMgr.verifyLock(item.id, item.token, this.getLockContext())) {
237
+ if (item.token && !lockMgr.verifyLock(item.id, item.token, lockCtx)) {
320
238
  throw new Error(`Invalid or expired lock token for job ${item.id}`);
321
239
  }
322
240
  }
323
- await ackJobBatchWithResults(items, this.getAckContext());
241
+ await ackJobBatchWithResults(items, this.contextFactory.getAckContext());
324
242
  for (const item of items) {
325
- lockMgr.releaseLock(item.id, this.getLockContext(), item.token);
243
+ lockMgr.releaseLock(item.id, lockCtx, item.token);
326
244
  }
327
245
  }
328
246
  async fail(jobId, error, token) {
329
- if (token && !lockMgr.verifyLock(jobId, token, this.getLockContext())) {
247
+ const lockCtx = this.contextFactory.getLockContext();
248
+ if (token && !lockMgr.verifyLock(jobId, token, lockCtx)) {
330
249
  throw new Error(`Invalid or expired lock token for job ${jobId}`);
331
250
  }
332
- await failJob(jobId, error, this.getAckContext());
333
- lockMgr.releaseLock(jobId, this.getLockContext(), token);
251
+ await failJob(jobId, error, this.contextFactory.getAckContext());
252
+ lockMgr.releaseLock(jobId, lockCtx, token);
334
253
  }
335
254
  jobHeartbeat(jobId, token) {
336
255
  const loc = this.jobIndex.get(jobId);
337
256
  if (loc?.type !== 'processing')
338
257
  return false;
339
258
  if (token) {
340
- return lockMgr.renewJobLock(jobId, token, this.getLockContext());
259
+ return lockMgr.renewJobLock(jobId, token, this.contextFactory.getLockContext());
341
260
  }
342
261
  const processing = this.processingShards[loc.shardIdx];
343
262
  const job = processing.get(jobId);
@@ -355,66 +274,66 @@ export class QueueManager {
355
274
  }
356
275
  return count;
357
276
  }
358
- // ============ Lock Management (delegated) ============
277
+ // ============ Lock Management ============
359
278
  createLock(jobId, owner, ttl = DEFAULT_LOCK_TTL) {
360
- return lockMgr.createLock(jobId, owner, this.getLockContext(), ttl);
279
+ return lockMgr.createLock(jobId, owner, this.contextFactory.getLockContext(), ttl);
361
280
  }
362
281
  verifyLock(jobId, token) {
363
- return lockMgr.verifyLock(jobId, token, this.getLockContext());
282
+ return lockMgr.verifyLock(jobId, token, this.contextFactory.getLockContext());
364
283
  }
365
284
  renewJobLock(jobId, token, newTtl) {
366
- return lockMgr.renewJobLock(jobId, token, this.getLockContext(), newTtl);
285
+ return lockMgr.renewJobLock(jobId, token, this.contextFactory.getLockContext(), newTtl);
367
286
  }
368
287
  renewJobLockBatch(items) {
369
- return lockMgr.renewJobLockBatch(items, this.getLockContext());
288
+ return lockMgr.renewJobLockBatch(items, this.contextFactory.getLockContext());
370
289
  }
371
290
  releaseLock(jobId, token) {
372
- return lockMgr.releaseLock(jobId, this.getLockContext(), token);
291
+ return lockMgr.releaseLock(jobId, this.contextFactory.getLockContext(), token);
373
292
  }
374
293
  getLockInfo(jobId) {
375
- return lockMgr.getLockInfo(jobId, this.getLockContext());
294
+ return lockMgr.getLockInfo(jobId, this.contextFactory.getLockContext());
376
295
  }
377
- // ============ Client-Job Tracking (delegated) ============
296
+ // ============ Client-Job Tracking ============
378
297
  registerClientJob(clientId, jobId) {
379
- lockMgr.registerClientJob(clientId, jobId, this.getLockContext());
298
+ lockMgr.registerClientJob(clientId, jobId, this.contextFactory.getLockContext());
380
299
  }
381
300
  unregisterClientJob(clientId, jobId) {
382
- lockMgr.unregisterClientJob(clientId, jobId, this.getLockContext());
301
+ lockMgr.unregisterClientJob(clientId, jobId, this.contextFactory.getLockContext());
383
302
  }
384
303
  releaseClientJobs(clientId) {
385
- return lockMgr.releaseClientJobs(clientId, this.getLockContext());
304
+ return lockMgr.releaseClientJobs(clientId, this.contextFactory.getLockContext());
386
305
  }
387
- // ============ Query Operations (delegated) ============
306
+ // ============ Query Operations ============
388
307
  async getJob(jobId) {
389
- return queryOps.getJob(jobId, this.getQueryContext());
308
+ return queryOps.getJob(jobId, this.contextFactory.getQueryContext());
390
309
  }
391
310
  getResult(jobId) {
392
- return queryOps.getJobResult(jobId, this.getQueryContext());
311
+ return queryOps.getJobResult(jobId, this.contextFactory.getQueryContext());
393
312
  }
394
313
  getJobByCustomId(customId) {
395
- return queryOps.getJobByCustomId(customId, this.getQueryContext());
314
+ return queryOps.getJobByCustomId(customId, this.contextFactory.getQueryContext());
396
315
  }
397
316
  getProgress(jobId) {
398
- return queryOps.getJobProgress(jobId, this.getQueryContext());
317
+ return queryOps.getJobProgress(jobId, this.contextFactory.getQueryContext());
399
318
  }
400
319
  count(queue) {
401
- return queueControl.getQueueCount(queue, { shards: this.shards, jobIndex: this.jobIndex });
320
+ return queueControl.getQueueCount(queue, this.contextFactory.getQueueControlContext());
402
321
  }
403
- // ============ Queue Control (delegated) ============
322
+ // ============ Queue Control ============
404
323
  pause(queue) {
405
- queueControl.pauseQueue(queue, { shards: this.shards, jobIndex: this.jobIndex });
324
+ queueControl.pauseQueue(queue, this.contextFactory.getQueueControlContext());
406
325
  }
407
326
  resume(queue) {
408
- queueControl.resumeQueue(queue, { shards: this.shards, jobIndex: this.jobIndex });
327
+ queueControl.resumeQueue(queue, this.contextFactory.getQueueControlContext());
409
328
  }
410
329
  isPaused(queue) {
411
- return queueControl.isQueuePaused(queue, { shards: this.shards, jobIndex: this.jobIndex });
330
+ return queueControl.isQueuePaused(queue, this.contextFactory.getQueueControlContext());
412
331
  }
413
332
  drain(queue) {
414
- return queueControl.drainQueue(queue, { shards: this.shards, jobIndex: this.jobIndex });
333
+ return queueControl.drainQueue(queue, this.contextFactory.getQueueControlContext());
415
334
  }
416
335
  obliterate(queue) {
417
- queueControl.obliterateQueue(queue, { shards: this.shards, jobIndex: this.jobIndex });
336
+ queueControl.obliterateQueue(queue, this.contextFactory.getQueueControlContext());
418
337
  this.unregisterQueueName(queue);
419
338
  }
420
339
  listQueues() {
@@ -427,7 +346,7 @@ export class QueueManager {
427
346
  this.queueNamesCache.delete(queue);
428
347
  }
429
348
  clean(queue, graceMs, state, limit) {
430
- return queueControl.cleanQueue(queue, graceMs, { shards: this.shards, jobIndex: this.jobIndex }, state, limit);
349
+ return queueControl.cleanQueue(queue, graceMs, this.contextFactory.getQueueControlContext(), state, limit);
431
350
  }
432
351
  getCountsPerPriority(queue) {
433
352
  const idx = shardIndex(queue);
@@ -435,80 +354,24 @@ export class QueueManager {
435
354
  return Object.fromEntries(counts);
436
355
  }
437
356
  getJobs(queue, options = {}) {
438
- const { state, start = 0, end = 100, asc = true } = options;
439
357
  const idx = shardIndex(queue);
440
- const shard = this.shards[idx];
441
- const now = Date.now();
442
- const jobs = [];
443
- if (!state || state === 'waiting') {
444
- jobs.push(...shard
445
- .getQueue(queue)
446
- .values()
447
- .filter((j) => j.runAt <= now));
448
- }
449
- if (!state || state === 'delayed') {
450
- jobs.push(...shard
451
- .getQueue(queue)
452
- .values()
453
- .filter((j) => j.runAt > now));
454
- }
455
- if (!state || state === 'active') {
456
- for (let i = 0; i < SHARD_COUNT; i++) {
457
- for (const job of this.processingShards[i].values()) {
458
- if (job.queue === queue)
459
- jobs.push(job);
460
- }
461
- }
462
- }
463
- if (!state || state === 'failed') {
464
- jobs.push(...shard.getDlq(queue));
465
- }
466
- jobs.sort((a, b) => (asc ? a.createdAt - b.createdAt : b.createdAt - a.createdAt));
467
- return jobs.slice(start, end);
358
+ return queryOps.getJobs(queue, idx, options, {
359
+ ...this.contextFactory.getQueryContext(),
360
+ shardCount: SHARD_COUNT,
361
+ });
468
362
  }
469
- // ============ DLQ Operations (delegated) ============
363
+ // ============ DLQ Operations ============
470
364
  getDlq(queue, count) {
471
- return dlqOps.getDlqJobs(queue, this.getDlqContext(), count);
365
+ return dlqOps.getDlqJobs(queue, this.contextFactory.getDlqContext(), count);
472
366
  }
473
367
  retryDlq(queue, jobId) {
474
- return dlqOps.retryDlqJobs(queue, this.getDlqContext(), jobId);
368
+ return dlqOps.retryDlqJobs(queue, this.contextFactory.getDlqContext(), jobId);
475
369
  }
476
370
  purgeDlq(queue) {
477
- return dlqOps.purgeDlqJobs(queue, this.getDlqContext());
371
+ return dlqOps.purgeDlqJobs(queue, this.contextFactory.getDlqContext());
478
372
  }
479
373
  retryCompleted(queue, jobId) {
480
- if (jobId) {
481
- if (!this.completedJobs.has(jobId))
482
- return 0;
483
- const job = this.storage?.getJob(jobId);
484
- if (job?.queue !== queue)
485
- return 0;
486
- return this.requeueCompletedJob(job);
487
- }
488
- let count = 0;
489
- for (const id of this.completedJobs) {
490
- const job = this.storage?.getJob(id);
491
- if (job?.queue === queue)
492
- count += this.requeueCompletedJob(job);
493
- }
494
- return count;
495
- }
496
- requeueCompletedJob(job) {
497
- job.attempts = 0;
498
- job.startedAt = null;
499
- job.completedAt = null;
500
- job.runAt = Date.now();
501
- job.progress = 0;
502
- const idx = shardIndex(job.queue);
503
- const shard = this.shards[idx];
504
- shard.getQueue(job.queue).push(job);
505
- shard.incrementQueued(job.id, false, job.createdAt, job.queue, job.runAt);
506
- this.jobIndex.set(job.id, { type: 'queue', shardIdx: idx, queueName: job.queue });
507
- this.completedJobs.delete(job.id);
508
- this.jobResults.delete(job.id);
509
- this.storage?.updateForRetry(job);
510
- shard.notify();
511
- return 1;
374
+ return dlqOps.retryCompletedJobs(queue, this.contextFactory.getRetryCompletedContext(), jobId);
512
375
  }
513
376
  // ============ Rate Limiting ============
514
377
  setRateLimit(queue, limit) {
@@ -523,45 +386,37 @@ export class QueueManager {
523
386
  clearConcurrency(queue) {
524
387
  this.shards[shardIndex(queue)].clearConcurrency(queue);
525
388
  }
526
- // ============ Job Management (delegated) ============
389
+ // ============ Job Management ============
527
390
  async cancel(jobId) {
528
- return jobMgmt.cancelJob(jobId, this.getJobMgmtContext());
391
+ return jobMgmt.cancelJob(jobId, this.contextFactory.getJobMgmtContext());
529
392
  }
530
393
  async updateProgress(jobId, progress, message) {
531
- return jobMgmt.updateJobProgress(jobId, progress, this.getJobMgmtContext(), message);
394
+ return jobMgmt.updateJobProgress(jobId, progress, this.contextFactory.getJobMgmtContext(), message);
532
395
  }
533
396
  async updateJobData(jobId, data) {
534
- return jobMgmt.updateJobData(jobId, data, this.getJobMgmtContext());
397
+ return jobMgmt.updateJobData(jobId, data, this.contextFactory.getJobMgmtContext());
535
398
  }
536
399
  async changePriority(jobId, priority) {
537
- return jobMgmt.changeJobPriority(jobId, priority, this.getJobMgmtContext());
400
+ return jobMgmt.changeJobPriority(jobId, priority, this.contextFactory.getJobMgmtContext());
538
401
  }
539
402
  async promote(jobId) {
540
- return jobMgmt.promoteJob(jobId, this.getJobMgmtContext());
403
+ return jobMgmt.promoteJob(jobId, this.contextFactory.getJobMgmtContext());
541
404
  }
542
405
  async moveToDelayed(jobId, delay) {
543
- return jobMgmt.moveJobToDelayed(jobId, delay, this.getJobMgmtContext());
406
+ return jobMgmt.moveJobToDelayed(jobId, delay, this.contextFactory.getJobMgmtContext());
544
407
  }
545
408
  async discard(jobId) {
546
- return jobMgmt.discardJob(jobId, this.getJobMgmtContext());
409
+ return jobMgmt.discardJob(jobId, this.contextFactory.getJobMgmtContext());
547
410
  }
548
- // ============ Job Logs (delegated) ============
411
+ // ============ Job Logs ============
549
412
  addLog(jobId, message, level = 'info') {
550
- return logsOps.addJobLog(jobId, message, { jobIndex: this.jobIndex, jobLogs: this.jobLogs, maxLogsPerJob: this.maxLogsPerJob }, level);
413
+ return logsOps.addJobLog(jobId, message, this.contextFactory.getLogsContext(), level);
551
414
  }
552
415
  getLogs(jobId) {
553
- return logsOps.getJobLogs(jobId, {
554
- jobIndex: this.jobIndex,
555
- jobLogs: this.jobLogs,
556
- maxLogsPerJob: this.maxLogsPerJob,
557
- });
416
+ return logsOps.getJobLogs(jobId, this.contextFactory.getLogsContext());
558
417
  }
559
418
  clearLogs(jobId) {
560
- logsOps.clearJobLogs(jobId, {
561
- jobIndex: this.jobIndex,
562
- jobLogs: this.jobLogs,
563
- maxLogsPerJob: this.maxLogsPerJob,
564
- });
419
+ logsOps.clearJobLogs(jobId, this.contextFactory.getLogsContext());
565
420
  }
566
421
  // ============ Metrics ============
567
422
  getPrometheusMetrics() {
@@ -599,7 +454,6 @@ export class QueueManager {
599
454
  getCompletedJobs() {
600
455
  return this.completedJobs;
601
456
  }
602
- /** Expose shards for testing (internal use only) */
603
457
  getShards() {
604
458
  return this.shards;
605
459
  }
@@ -617,15 +471,15 @@ export class QueueManager {
617
471
  }
618
472
  return false;
619
473
  }
620
- // ============ Stats (delegated) ============
474
+ // ============ Stats ============
621
475
  getStats() {
622
- return statsMgr.getStats(this.getStatsContext(), this.cronScheduler);
476
+ return statsMgr.getStats(this.contextFactory.getStatsContext(), this.cronScheduler);
623
477
  }
624
478
  getMemoryStats() {
625
- return statsMgr.getMemoryStats(this.getStatsContext());
479
+ return statsMgr.getMemoryStats(this.contextFactory.getStatsContext());
626
480
  }
627
481
  compactMemory() {
628
- statsMgr.compactMemory(this.getStatsContext());
482
+ statsMgr.compactMemory(this.contextFactory.getStatsContext());
629
483
  }
630
484
  // ============ Lifecycle ============
631
485
  shutdown() {