@stonyx/cron 0.2.1-alpha.29 → 0.2.1-alpha.30

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/dist/service.d.ts CHANGED
@@ -119,26 +119,6 @@ export default class CronService {
119
119
  * for and allows concurrent `onJobDue` invocations for the same job.
120
120
  */
121
121
  executeJob(job: Job): Promise<ExecuteResult>;
122
- /**
123
- * Phase 1 - claim. Must be called while holding the lock (`locked()`, whose
124
- * chain is module-global and therefore shared across CronService instances).
125
- *
126
- * Returns `null` on a successful claim, or the reason the claim was refused.
127
- * "already running" is what makes a second `run()` report a skip instead of
128
- * launching a concurrent invocation. "removed" covers the job being deleted
129
- * between `run()`'s unlocked lookup and this lock turn - claiming then would
130
- * `markRunning` an orphan and, worse, `removeFromHeap` an id that may now
131
- * belong to a replacement.
132
- *
133
- * Detaching from the heap here (rather than relying on phase 3 to push a
134
- * fresh entry) is what keeps manual runs from permanently duplicating heap
135
- * entries.
136
- */
137
- claimJob(job: Job): 'already running' | 'removed' | null;
138
- /**
139
- * Phase 3 - settle. Must be called while holding the lock.
140
- */
141
- settleJob(job: Job, status: string, error: string | undefined, summary: string | undefined, startMs: number, durationMs: number): ExecuteResult;
142
122
  removeFromHeap(id: string): void;
143
123
  log(message: string): void;
144
124
  }
package/dist/service.js CHANGED
@@ -290,7 +290,7 @@ export default class CronService {
290
290
  */
291
291
  async executeJob(job) {
292
292
  // -- Phase 1: claim (locked) --
293
- const refusal = await locked(() => this.claimJob(job));
293
+ const refusal = await locked(() => this.#claimJob(job));
294
294
  if (refusal)
295
295
  return { status: 'skipped', reason: refusal };
296
296
  return this.#executeClaimed(job);
@@ -306,7 +306,7 @@ export default class CronService {
306
306
  // Membership re-check. The claim and the invoke are no longer in the same
307
307
  // critical section, and sibling callbacks run unlocked, so a `remove()` can
308
308
  // land in between AND RESOLVE - it used to deadlock. A resolved `remove()`
309
- // must keep meaning "this callback will not fire": settleJob's identity
309
+ // must keep meaning "this callback will not fire": #settleJob's identity
310
310
  // guard only cleans up afterwards, by which point the side effect has
311
311
  // already happened. Identity, not id, so a removed-then-replaced key is
312
312
  // caught too. Deliberately synchronous with the `onJobDue` call below -
@@ -315,7 +315,7 @@ export default class CronService {
315
315
  // This is the ONE early return in the phase-2/3 control flow that happens
316
316
  // after a claim, so it is the one that has to release the claim by hand.
317
317
  // (`executeJob`'s refusal return at the call site is pre-claim; `onTimer`'s
318
- // re-entrancy return never claims; every return inside `settleJob` is
318
+ // re-entrancy return never claims; every return inside `#settleJob` is
319
319
  // already past phase 3.)
320
320
  //
321
321
  // Skipping settle entirely here is right - re-inserting or run-logging a
@@ -368,7 +368,7 @@ export default class CronService {
368
368
  }
369
369
  finally {
370
370
  // -- Phase 3: settle (locked) --
371
- settled = await locked(() => this.settleJob(job, status, error, summary, startMs, Date.now() - startMs));
371
+ settled = await locked(() => this.#settleJob(job, status, error, summary, startMs, Date.now() - startMs));
372
372
  }
373
373
  return settled;
374
374
  }
@@ -376,6 +376,15 @@ export default class CronService {
376
376
  * Phase 1 - claim. Must be called while holding the lock (`locked()`, whose
377
377
  * chain is module-global and therefore shared across CronService instances).
378
378
  *
379
+ * `#private`, like `#executeClaimed` and for the same reason. Published, this
380
+ * was a supported call performing `markRunning` + `removeFromHeap` with no
381
+ * guaranteed settle - the claim-without-settle shape the try/finally in
382
+ * `#executeClaimed` exists to prevent, and with no lease on `runningAtMs` a
383
+ * single such call permanently strands the job: off the heap, marked running,
384
+ * with nothing that will ever release it. The precondition below cannot be
385
+ * expressed in the type system, so the method must not be reachable from
386
+ * outside the class body.
387
+ *
379
388
  * Returns `null` on a successful claim, or the reason the claim was refused.
380
389
  * "already running" is what makes a second `run()` report a skip instead of
381
390
  * launching a concurrent invocation. "removed" covers the job being deleted
@@ -387,7 +396,7 @@ export default class CronService {
387
396
  * fresh entry) is what keeps manual runs from permanently duplicating heap
388
397
  * entries.
389
398
  */
390
- claimJob(job) {
399
+ #claimJob(job) {
391
400
  if (this.jobs.get(job.id) !== job)
392
401
  return 'removed';
393
402
  if (job.state.runningAtMs)
@@ -398,8 +407,13 @@ export default class CronService {
398
407
  }
399
408
  /**
400
409
  * Phase 3 - settle. Must be called while holding the lock.
410
+ *
411
+ * `#private` for the same reason as `#claimJob`: unlocked it would run
412
+ * `applyResult`, a `runLog.record`, a full `removeFromHeap` rebuild, a
413
+ * `heap.push` and an `armTimer` with no mutual exclusion - exactly the
414
+ * corruption `locked()` exists to prevent.
401
415
  */
402
- settleJob(job, status, error, summary, startMs, durationMs) {
416
+ #settleJob(job, status, error, summary, startMs, durationMs) {
403
417
  try {
404
418
  const validStatus = (status === 'ok' || status === 'error' || status === 'skipped') ? status : 'error';
405
419
  applyResult(job, validStatus, error, durationMs);
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "keywords": [
4
4
  "stonyx-module"
5
5
  ],
6
- "version": "0.2.1-alpha.29",
6
+ "version": "0.2.1-alpha.30",
7
7
  "description": "Cron/job scheduler for Stonyx framework",
8
8
  "main": "dist/main.js",
9
9
  "types": "dist/main.d.ts",