@arkstack/scheduler 0.19.2 → 0.19.3

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/README.md CHANGED
@@ -18,19 +18,19 @@ Full app templates include it and a `src/routes/console.ts` already.
18
18
  In `src/routes/console.ts`:
19
19
 
20
20
  ```ts
21
- import { Schedule } from '@arkstack/scheduler';
21
+ import { Schedule } from '@arkstack/scheduler'
22
22
 
23
- Schedule.command('cache:prune').hourly();
23
+ Schedule.command('cache:prune').hourly()
24
24
 
25
25
  Schedule.call(async () => {
26
- await pruneTempFiles();
26
+ await pruneTempFiles()
27
27
  })
28
28
  .dailyAt('01:30')
29
- .withoutOverlapping();
29
+ .withoutOverlapping()
30
30
 
31
- Schedule.job(new SendDigest()).weeklyOn(1, '08:00');
31
+ Schedule.job(new SendDigest()).weeklyOn(1, '08:00')
32
32
 
33
- Schedule.exec('backup.sh').daily().onOneServer();
33
+ Schedule.exec('backup.sh').daily().onOneServer()
34
34
  ```
35
35
 
36
36
  | Task type | Runs |
@@ -58,36 +58,36 @@ ark schedule:list # list tasks with their next run time
58
58
  ## Frequencies
59
59
 
60
60
  ```ts
61
- Schedule.command('x').everyMinute();
62
- Schedule.command('x').everyFiveMinutes(); // */5 * * * *
63
- Schedule.command('x').everyThirtyMinutes();
64
- Schedule.command('x').hourly();
65
- Schedule.command('x').hourlyAt(15);
66
- Schedule.command('x').daily();
67
- Schedule.command('x').dailyAt('13:00');
68
- Schedule.command('x').twiceDaily(1, 13);
69
- Schedule.command('x').weekly();
70
- Schedule.command('x').weeklyOn(1, '8:00'); // Monday 08:00
71
- Schedule.command('x').monthly();
72
- Schedule.command('x').monthlyOn(15, '17:00');
73
- Schedule.command('x').quarterly();
74
- Schedule.command('x').yearly();
75
- Schedule.command('x').cron('*/10 9-17 * * 1-5'); // raw cron
61
+ Schedule.command('x').everyMinute()
62
+ Schedule.command('x').everyFiveMinutes() // */5 * * * *
63
+ Schedule.command('x').everyThirtyMinutes()
64
+ Schedule.command('x').hourly()
65
+ Schedule.command('x').hourlyAt(15)
66
+ Schedule.command('x').daily()
67
+ Schedule.command('x').dailyAt('13:00')
68
+ Schedule.command('x').twiceDaily(1, 13)
69
+ Schedule.command('x').weekly()
70
+ Schedule.command('x').weeklyOn(1, '8:00') // Monday 08:00
71
+ Schedule.command('x').monthly()
72
+ Schedule.command('x').monthlyOn(15, '17:00')
73
+ Schedule.command('x').quarterly()
74
+ Schedule.command('x').yearly()
75
+ Schedule.command('x').cron('*/10 9-17 * * 1-5') // raw cron
76
76
  ```
77
77
 
78
78
  Day-of-week constraints, with time layered on top:
79
79
 
80
80
  ```ts
81
- Schedule.command('x').weekdays().at('9:00');
82
- Schedule.command('x').weekends().hourly();
83
- Schedule.command('x').mondays();
84
- Schedule.command('x').days([1, 4]); // Monday & Thursday
81
+ Schedule.command('x').weekdays().at('9:00')
82
+ Schedule.command('x').weekends().hourly()
83
+ Schedule.command('x').mondays()
84
+ Schedule.command('x').days([1, 4]) // Monday & Thursday
85
85
  ```
86
86
 
87
87
  Set the timezone the expression is evaluated in:
88
88
 
89
89
  ```ts
90
- Schedule.command('x').dailyAt('09:00').timezone('America/New_York');
90
+ Schedule.command('x').dailyAt('09:00').timezone('America/New_York')
91
91
  ```
92
92
 
93
93
  ## Constraints
@@ -98,7 +98,7 @@ Schedule.command('x')
98
98
  .when(async () => await featureEnabled('reports')) // run only when truthy
99
99
  .skip(() => isHoliday()) // skip when truthy
100
100
  .environments('production', 'staging') // limit by APP_ENV
101
- .between('09:00', '17:00'); // only within a daily window
101
+ .between('09:00', '17:00') // only within a daily window
102
102
  ```
103
103
 
104
104
  `unlessBetween('22:00', '06:00')` runs _outside_ a window (overnight ranges handled).
@@ -106,9 +106,9 @@ Schedule.command('x')
106
106
  ## Overlaps, single-server & background
107
107
 
108
108
  ```ts
109
- Schedule.command('report:build').everyFiveMinutes().withoutOverlapping();
110
- Schedule.exec('backup.sh').daily().onOneServer();
111
- Schedule.exec('long-import.sh').daily().runInBackground();
109
+ Schedule.command('report:build').everyFiveMinutes().withoutOverlapping()
110
+ Schedule.exec('backup.sh').daily().onOneServer()
111
+ Schedule.exec('long-import.sh').daily().runInBackground()
112
112
  ```
113
113
 
114
114
  `withoutOverlapping()` and `onOneServer()` coordinate through `@arkstack/cache`, so they work across processes and servers. Configure a shared cache store (`redis` or `database`) for `onOneServer()` to be effective; without a cache the scheduler falls back to a process-local lock.
@@ -121,7 +121,7 @@ Schedule.command('report:build')
121
121
  .before(() => logger.info('building report'))
122
122
  .onSuccess(() => notifyOk())
123
123
  .onFailure((error) => notifyFailed(error))
124
- .after(() => logger.info('done'));
124
+ .after(() => logger.info('done'))
125
125
  ```
126
126
 
127
127
  ## API
@@ -1,4 +1,4 @@
1
- import { n as Schedule, t as loadSchedule } from "../loader-CZcEYUX9.js";
1
+ import { n as Schedule, t as loadSchedule } from "../loader-DlxdvHFL.js";
2
2
  import { Command } from "@h3ravel/musket";
3
3
  //#region src/commands/ScheduleListCommand.ts
4
4
  /**
@@ -1,5 +1,5 @@
1
- import { t as loadSchedule } from "../loader-CZcEYUX9.js";
2
- import { t as runDueEvents } from "../runner-Bt-jQptE.js";
1
+ import { t as loadSchedule } from "../loader-DlxdvHFL.js";
2
+ import { t as runDueEvents } from "../runner-b2r6TZPd.js";
3
3
  import { Command } from "@h3ravel/musket";
4
4
  //#region src/commands/ScheduleRunCommand.ts
5
5
  /**
@@ -1,5 +1,5 @@
1
- import { t as loadSchedule } from "../loader-CZcEYUX9.js";
2
- import { t as runDueEvents } from "../runner-Bt-jQptE.js";
1
+ import { t as loadSchedule } from "../loader-DlxdvHFL.js";
2
+ import { t as runDueEvents } from "../runner-b2r6TZPd.js";
3
3
  import { Command } from "@h3ravel/musket";
4
4
  //#region src/commands/ScheduleWorkCommand.ts
5
5
  /**
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
- import { a as nextRun, i as isDue, n as Schedule, o as acquireLock, r as ScheduledEvent, s as releaseLock, t as loadSchedule } from "./loader-CZcEYUX9.js";
2
- import { t as runDueEvents } from "./runner-Bt-jQptE.js";
1
+ import { a as nextRun, i as isDue, n as Schedule, o as acquireLock, r as ScheduledEvent, s as releaseLock, t as loadSchedule } from "./loader-DlxdvHFL.js";
2
+ import { t as runDueEvents } from "./runner-b2r6TZPd.js";
3
3
  export { Schedule, ScheduledEvent, acquireLock, isDue, loadSchedule, nextRun, releaseLock, runDueEvents };
@@ -280,42 +280,42 @@ var ScheduledEvent = class {
280
280
  this.timezoneValue = timezone;
281
281
  return this;
282
282
  }
283
- /**
283
+ /**
284
284
  * Only run when every registered `when` predicate is truthy.
285
- *
286
- * @param callback
287
- * @returns
285
+ *
286
+ * @param callback
287
+ * @returns
288
288
  */
289
289
  when(callback) {
290
290
  this.filters.push(callback);
291
291
  return this;
292
292
  }
293
- /**
293
+ /**
294
294
  * Skip when any registered `skip` predicate is truthy.
295
- *
296
- * @param callback
297
- * @returns
295
+ *
296
+ * @param callback
297
+ * @returns
298
298
  */
299
299
  skip(callback) {
300
300
  this.rejects.push(callback);
301
301
  return this;
302
302
  }
303
- /**
303
+ /**
304
304
  * Only run in these `APP_ENV` environments.
305
- *
306
- * @param callback
307
- * @returns
305
+ *
306
+ * @param callback
307
+ * @returns
308
308
  */
309
309
  environments(...environments) {
310
310
  this.environmentsValue = environments.flat();
311
311
  return this;
312
312
  }
313
- /**
314
- * Only run when the current time is within `[start, end]` (HH:MM, event tz).
315
- *
316
- * @param start
317
- * @param end
318
- * @returns
313
+ /**
314
+ * Only run when the current time is within `[start, end]` (HH:MM, event tz).
315
+ *
316
+ * @param start
317
+ * @param end
318
+ * @returns
319
319
  */
320
320
  between(start, end) {
321
321
  this.windows.push({
@@ -325,11 +325,11 @@ var ScheduledEvent = class {
325
325
  });
326
326
  return this;
327
327
  }
328
- /**
328
+ /**
329
329
  * Only run when the current time is outside `[start, end]`.
330
- *
331
- * @param callback
332
- * @returns
330
+ *
331
+ * @param callback
332
+ * @returns
333
333
  */
334
334
  unlessBetween(start, end) {
335
335
  this.windows.push({
@@ -343,52 +343,52 @@ var ScheduledEvent = class {
343
343
  const [h, m] = parseTime(time);
344
344
  return h * 60 + m;
345
345
  }
346
- /**
347
- * Prevent the task from overlapping itself; the lock expires after `expiresMinutes`.
348
- *
349
- * @param expiresMinutes
350
- * @returns
346
+ /**
347
+ * Prevent the task from overlapping itself; the lock expires after `expiresMinutes`.
348
+ *
349
+ * @param expiresMinutes
350
+ * @returns
351
351
  */
352
352
  withoutOverlapping(expiresMinutes = 1440) {
353
353
  this.withoutOverlappingValue = true;
354
354
  this.overlapExpiresMinutes = expiresMinutes;
355
355
  return this;
356
356
  }
357
- /**
357
+ /**
358
358
  * Run on only one server per due minute (requires a shared cache store).
359
- *
360
- * @param callback
361
- * @returns
359
+ *
360
+ * @param callback
361
+ * @returns
362
362
  */
363
363
  onOneServer() {
364
364
  this.onOneServerValue = true;
365
365
  return this;
366
366
  }
367
- /**
367
+ /**
368
368
  * Run the task in a detached background process (command/exec only).
369
- *
370
- * @param callback
371
- * @returns
369
+ *
370
+ * @param callback
371
+ * @returns
372
372
  */
373
373
  runInBackground() {
374
374
  this.runInBackgroundValue = true;
375
375
  return this;
376
376
  }
377
- /**
377
+ /**
378
378
  * A human description shown by `schedule:list`.
379
- *
380
- * @param callback
381
- * @returns
379
+ *
380
+ * @param callback
381
+ * @returns
382
382
  */
383
383
  description(description) {
384
384
  this.descriptionValue = description;
385
385
  return this;
386
386
  }
387
- /**
387
+ /**
388
388
  * An explicit mutex name (otherwise derived from the expression + description).
389
- *
390
- * @param name
391
- * @returns
389
+ *
390
+ * @param name
391
+ * @returns
392
392
  */
393
393
  name(name) {
394
394
  this.mutexNameValue = name;
@@ -410,29 +410,29 @@ var ScheduledEvent = class {
410
410
  this.failureHooks.push(hook);
411
411
  return this;
412
412
  }
413
- /**
414
- * Whether the cron expression is due at `date`.
415
- *
416
- * @param date
417
- * @returns
413
+ /**
414
+ * Whether the cron expression is due at `date`.
415
+ *
416
+ * @param date
417
+ * @returns
418
418
  */
419
419
  isDue(date = /* @__PURE__ */ new Date()) {
420
420
  return isDue(this.expression, date, this.timezoneValue);
421
421
  }
422
- /**
423
- * The next time this event will run after `from`.
424
- *
425
- * @param date
426
- * @returns
422
+ /**
423
+ * The next time this event will run after `from`.
424
+ *
425
+ * @param date
426
+ * @returns
427
427
  */
428
428
  nextRunAt(from = /* @__PURE__ */ new Date()) {
429
429
  return nextRun(this.expression, from, this.timezoneValue);
430
430
  }
431
- /**
432
- * Whether environment, time-window, `when` and `skip` constraints all pass.
433
- *
434
- * @param date
435
- * @returns
431
+ /**
432
+ * Whether environment, time-window, `when` and `skip` constraints all pass.
433
+ *
434
+ * @param date
435
+ * @returns
436
436
  */
437
437
  async filtersPass(date = /* @__PURE__ */ new Date()) {
438
438
  if (this.environmentsValue) {
@@ -447,10 +447,10 @@ var ScheduledEvent = class {
447
447
  for (const reject of this.rejects) if (await reject()) return false;
448
448
  return true;
449
449
  }
450
- /**
450
+ /**
451
451
  * A stable mutex key derived from the expression + description (or an explicit name).
452
- *
453
- * @returns
452
+ *
453
+ * @returns
454
454
  */
455
455
  mutexName() {
456
456
  if (this.mutexNameValue) return `arkstack-schedule-${this.mutexNameValue}`;
@@ -568,70 +568,70 @@ const registry = () => {
568
568
  * ```
569
569
  */
570
570
  var Schedule = class {
571
- /**
571
+ /**
572
572
  * Run an Arkstack CLI command (`ark <name>`) on the schedule.
573
- *
574
- * @param name
575
- * @param args
576
- * @returns
573
+ *
574
+ * @param name
575
+ * @param args
576
+ * @returns
577
577
  */
578
578
  static command(name, args = []) {
579
579
  const event = new ScheduledEvent("command", `ark ${name}`).setProcess(name, args);
580
580
  return this.add(event);
581
581
  }
582
- /**
583
- * Run a callback on the schedule.
584
- *
585
- * @param callback
586
- * @returns
582
+ /**
583
+ * Run a callback on the schedule.
584
+ *
585
+ * @param callback
586
+ * @returns
587
587
  */
588
588
  static call(callback) {
589
589
  const event = new ScheduledEvent("call", "Closure").setCall(callback);
590
590
  return this.add(event);
591
591
  }
592
- /**
593
- * Dispatch a queued job on the schedule (requires `@arkstack/jobs`).
594
- *
595
- * @param callback
596
- * @returns
592
+ /**
593
+ * Dispatch a queued job on the schedule (requires `@arkstack/jobs`).
594
+ *
595
+ * @param callback
596
+ * @returns
597
597
  */
598
598
  static job(job) {
599
599
  const event = new ScheduledEvent("job", job?.constructor?.name ?? "Job").setJob(job);
600
600
  return this.add(event);
601
601
  }
602
- /**
603
- * Run a shell command on the schedule.
604
- *
605
- * @param callback
606
- * @returns
602
+ /**
603
+ * Run a shell command on the schedule.
604
+ *
605
+ * @param callback
606
+ * @returns
607
607
  */
608
608
  static exec(command, args = []) {
609
609
  const event = new ScheduledEvent("exec", [command, ...args].join(" ")).setProcess(command, args);
610
610
  return this.add(event);
611
611
  }
612
- /**
613
- * All registered events.
614
- *
615
- * @param callback
616
- * @returns
612
+ /**
613
+ * All registered events.
614
+ *
615
+ * @param callback
616
+ * @returns
617
617
  */
618
618
  static events() {
619
619
  return registry();
620
620
  }
621
- /**
622
- * Events whose cron expression is due at `date`.
623
- *
624
- * @param callback
625
- * @returns
621
+ /**
622
+ * Events whose cron expression is due at `date`.
623
+ *
624
+ * @param callback
625
+ * @returns
626
626
  */
627
627
  static dueEvents(date = /* @__PURE__ */ new Date()) {
628
628
  return registry().filter((event) => event.isDue(date));
629
629
  }
630
- /**
631
- * Remove all registered events (used in tests).
632
- *
633
- * @param callback
634
- * @returns
630
+ /**
631
+ * Remove all registered events (used in tests).
632
+ *
633
+ * @param callback
634
+ * @returns
635
635
  */
636
636
  static clear() {
637
637
  registry().length = 0;
@@ -1,4 +1,4 @@
1
- import { n as Schedule } from "./loader-CZcEYUX9.js";
1
+ import { n as Schedule } from "./loader-DlxdvHFL.js";
2
2
  //#region src/runner.ts
3
3
  /**
4
4
  * Run every event that is due at `now` and whose filters pass, collecting a
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arkstack/scheduler",
3
- "version": "0.19.2",
3
+ "version": "0.19.3",
4
4
  "type": "module",
5
5
  "description": "Task scheduling for Arkstack: fluent frequencies, cron, overlap/one-server locks, hooks, and schedule:run/work/list commands.",
6
6
  "homepage": "https://arkstack.toneflix.net/guide/scheduling",
@@ -33,13 +33,13 @@
33
33
  },
34
34
  "dependencies": {
35
35
  "croner": "^9.0.0",
36
- "@arkstack/common": "^0.19.2"
36
+ "@arkstack/common": "^0.19.3"
37
37
  },
38
38
  "peerDependencies": {
39
39
  "@h3ravel/musket": "^2.2.13",
40
- "@arkstack/contract": "^0.19.2",
41
- "@arkstack/jobs": "^0.19.2",
42
- "@arkstack/cache": "^0.19.2"
40
+ "@arkstack/contract": "^0.19.3",
41
+ "@arkstack/jobs": "^0.19.3",
42
+ "@arkstack/cache": "^0.19.3"
43
43
  },
44
44
  "peerDependenciesMeta": {
45
45
  "@arkstack/cache": {