@checkstack/queue-bullmq-backend 0.1.5 → 0.2.0

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,32 @@
1
1
  # @checkstack/queue-bullmq-backend
2
2
 
3
+ ## 0.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 2c0822d: ### Queue System
8
+
9
+ - Added cron pattern support to `scheduleRecurring()` - accepts either `intervalSeconds` or `cronPattern`
10
+ - BullMQ backend uses native cron scheduling via `pattern` option
11
+ - InMemoryQueue implements wall-clock cron scheduling with `cron-parser`
12
+
13
+ ### Maintenance Backend
14
+
15
+ - Auto status transitions now use cron pattern `* * * * *` for precise second-0 scheduling
16
+ - User notifications are now sent for auto-started and auto-completed maintenances
17
+ - Refactored to call `addUpdate` RPC for status changes, centralizing hook/signal/notification logic
18
+
19
+ ### UI
20
+
21
+ - DateTimePicker now resets seconds and milliseconds to 0 when time is changed
22
+
23
+ ### Patch Changes
24
+
25
+ - Updated dependencies [2c0822d]
26
+ - Updated dependencies [66a3963]
27
+ - @checkstack/queue-api@0.2.0
28
+ - @checkstack/backend-api@0.5.0
29
+
3
30
  ## 0.1.5
4
31
 
5
32
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@checkstack/queue-bullmq-backend",
3
- "version": "0.1.5",
3
+ "version": "0.2.0",
4
4
  "type": "module",
5
5
  "main": "src/index.ts",
6
6
  "scripts": {
@@ -5,6 +5,7 @@ import {
5
5
  QueueStats,
6
6
  ConsumeOptions,
7
7
  RecurringJobDetails,
8
+ RecurringSchedule,
8
9
  } from "@checkstack/queue-api";
9
10
  import { Queue as BullQueue, Worker, JobsOptions } from "bullmq";
10
11
  import type { BullMQConfig } from "./plugin";
@@ -25,7 +26,10 @@ export class BullMQQueue<T = unknown> implements Queue<T> {
25
26
  private consumerGroups = new Map<string, ConsumerGroupState>();
26
27
  private stopped = false;
27
28
 
28
- constructor(private name: string, private config: BullMQConfig) {
29
+ constructor(
30
+ private name: string,
31
+ private config: BullMQConfig,
32
+ ) {
29
33
  // Initialize BullMQ Queue with Redis connection
30
34
  this.queue = new BullQueue(name, {
31
35
  connection: {
@@ -55,7 +59,7 @@ export class BullMQQueue<T = unknown> implements Queue<T> {
55
59
  } catch (error) {
56
60
  const message = error instanceof Error ? error.message : String(error);
57
61
  throw new Error(
58
- `Failed to connect to Redis at ${this.config.host}:${this.config.port}: ${message}`
62
+ `Failed to connect to Redis at ${this.config.host}:${this.config.port}: ${message}`,
59
63
  );
60
64
  }
61
65
  }
@@ -66,7 +70,7 @@ export class BullMQQueue<T = unknown> implements Queue<T> {
66
70
  priority?: number;
67
71
  startDelay?: number;
68
72
  jobId?: string;
69
- }
73
+ },
70
74
  ): Promise<string> {
71
75
  if (this.stopped) {
72
76
  throw new Error("Queue has been stopped");
@@ -93,7 +97,7 @@ export class BullMQQueue<T = unknown> implements Queue<T> {
93
97
 
94
98
  async consume(
95
99
  consumer: QueueConsumer<T>,
96
- options: ConsumeOptions
100
+ options: ConsumeOptions,
97
101
  ): Promise<void> {
98
102
  if (this.stopped) {
99
103
  throw new Error("Queue has been stopped");
@@ -138,7 +142,7 @@ export class BullMQQueue<T = unknown> implements Queue<T> {
138
142
  return Math.pow(2, attemptsMade) * 1000;
139
143
  },
140
144
  },
141
- }
145
+ },
142
146
  );
143
147
 
144
148
  // Configure retries at job level via job options
@@ -147,7 +151,7 @@ export class BullMQQueue<T = unknown> implements Queue<T> {
147
151
  // Max retries exhausted
148
152
  console.debug(
149
153
  `Job ${job.id} exhausted retries (${job.attemptsMade}/${maxRetries}):`,
150
- err
154
+ err,
151
155
  );
152
156
  }
153
157
  });
@@ -164,33 +168,29 @@ export class BullMQQueue<T = unknown> implements Queue<T> {
164
168
  data: T,
165
169
  options: {
166
170
  jobId: string;
167
- intervalSeconds: number;
168
- startDelay?: number;
169
171
  priority?: number;
170
- }
172
+ } & RecurringSchedule,
171
173
  ): Promise<string> {
172
174
  if (this.stopped) {
173
175
  throw new Error("Queue has been stopped");
174
176
  }
175
177
 
176
- const { jobId, intervalSeconds, startDelay, priority } = options;
178
+ const { jobId, priority } = options;
177
179
 
178
180
  // Use upsertJobScheduler for create-or-update semantics
181
+ // BullMQ supports either 'every' (interval) or 'pattern' (cron)
179
182
  await this.queue.upsertJobScheduler(
180
183
  jobId,
181
- {
182
- every: intervalSeconds * 1000,
183
- startDate: startDelay
184
- ? new Date(Date.now() + startDelay * 1000)
185
- : undefined,
186
- },
184
+ "cronPattern" in options && options.cronPattern
185
+ ? { pattern: options.cronPattern }
186
+ : { every: options.intervalSeconds! * 1000 },
187
187
  {
188
188
  name: this.name,
189
189
  data,
190
190
  opts: {
191
191
  priority,
192
192
  },
193
- }
193
+ },
194
194
  );
195
195
 
196
196
  return jobId;
@@ -214,7 +214,7 @@ export class BullMQQueue<T = unknown> implements Queue<T> {
214
214
  }
215
215
 
216
216
  async getRecurringJobDetails(
217
- jobId: string
217
+ jobId: string,
218
218
  ): Promise<RecurringJobDetails<T> | undefined> {
219
219
  if (this.stopped) {
220
220
  throw new Error("Queue has been stopped");
@@ -228,13 +228,21 @@ export class BullMQQueue<T = unknown> implements Queue<T> {
228
228
  }
229
229
 
230
230
  // BullMQ scheduler template contains the data
231
- return {
231
+ // Determine if it's cron-based or interval-based
232
+ const baseDetails = {
232
233
  jobId,
233
234
  data: scheduler.template?.data as T,
234
- intervalSeconds: scheduler.every ? scheduler.every / 1000 : 0,
235
235
  priority: scheduler.template?.opts?.priority,
236
236
  nextRunAt: scheduler.next ? new Date(scheduler.next) : undefined,
237
237
  };
238
+
239
+ if (scheduler.pattern) {
240
+ return { ...baseDetails, cronPattern: scheduler.pattern };
241
+ }
242
+ return {
243
+ ...baseDetails,
244
+ intervalSeconds: scheduler.every ? scheduler.every / 1000 : 0,
245
+ };
238
246
  }
239
247
 
240
248
  async getInFlightCount(): Promise<number> {
@@ -267,7 +275,7 @@ export class BullMQQueue<T = unknown> implements Queue<T> {
267
275
  "waiting",
268
276
  "active",
269
277
  "completed",
270
- "failed"
278
+ "failed",
271
279
  );
272
280
 
273
281
  return {