mongo-job-scheduler 0.1.9 → 0.1.10

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.
@@ -38,6 +38,9 @@ class Scheduler {
38
38
  // Normalize run time
39
39
  // ------------------------
40
40
  const nextRunAt = options.runAt ?? now;
41
+ if (isNaN(nextRunAt.getTime())) {
42
+ throw new Error("Invalid Date provided for runAt");
43
+ }
41
44
  const job = {
42
45
  name: options.name,
43
46
  data: options.data,
@@ -68,7 +71,7 @@ class Scheduler {
68
71
  if (options.repeat?.cron && options.repeat.every) {
69
72
  throw new Error("Cannot specify both cron and every");
70
73
  }
71
- return {
74
+ const job = {
72
75
  name: options.name,
73
76
  data: options.data,
74
77
  status: "pending",
@@ -77,6 +80,10 @@ class Scheduler {
77
80
  retry: options.retry,
78
81
  dedupeKey: options.dedupeKey,
79
82
  };
83
+ if (isNaN(job.nextRunAt.getTime())) {
84
+ throw new Error("Invalid Date provided for runAt");
85
+ }
86
+ return job;
80
87
  });
81
88
  const createdJobs = await this.store.createBulk(jobs);
82
89
  // Emit events for all created jobs
@@ -110,6 +117,17 @@ class Scheduler {
110
117
  if (!this.store) {
111
118
  throw new Error("Scheduler has no JobStore configured");
112
119
  }
120
+ // Require runAt when changing repeat to ensure deterministic behavior
121
+ if (updates.repeat && !updates.nextRunAt) {
122
+ throw new Error("nextRunAt is required when updating repeat");
123
+ }
124
+ if (updates.nextRunAt && isNaN(updates.nextRunAt.getTime())) {
125
+ throw new Error("Invalid Date provided for nextRunAt");
126
+ }
127
+ // If rescheduling, automatically reset status to pending
128
+ if (updates.nextRunAt) {
129
+ updates.status = "pending";
130
+ }
113
131
  await this.store.update(jobId, updates);
114
132
  }
115
133
  /**
@@ -147,6 +147,9 @@ class InMemoryJobStore {
147
147
  if (updates.repeat !== undefined) {
148
148
  job.repeat = updates.repeat;
149
149
  }
150
+ if (updates.status !== undefined) {
151
+ job.status = updates.status;
152
+ }
150
153
  job.updatedAt = new Date();
151
154
  }
152
155
  async findAll(query) {
@@ -1,4 +1,5 @@
1
1
  import { Job } from "../types/job";
2
+ import { JobStatus } from "../types/lifecycle";
2
3
  export interface JobStore {
3
4
  /**
4
5
  * Insert a new job
@@ -68,4 +69,5 @@ export interface JobUpdates {
68
69
  nextRunAt?: Date;
69
70
  retry?: RetryOptions;
70
71
  repeat?: RepeatOptions;
72
+ status?: JobStatus;
71
73
  }
@@ -210,6 +210,8 @@ class MongoJobStore {
210
210
  $set.retry = updates.retry;
211
211
  if (updates.repeat !== undefined)
212
212
  $set.repeat = updates.repeat;
213
+ if (updates.status !== undefined)
214
+ $set.status = updates.status;
213
215
  await this.collection.updateOne({ _id: id }, { $set });
214
216
  }
215
217
  async findAll(query) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mongo-job-scheduler",
3
- "version": "0.1.9",
3
+ "version": "0.1.10",
4
4
  "description": "Production-grade MongoDB-backed job scheduler with retries, cron, timezone support, and crash recovery",
5
5
  "license": "MIT",
6
6
  "author": "Darshan Bhut",