jm2 0.1.13 → 0.1.15

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jm2",
3
- "version": "0.1.13",
3
+ "version": "0.1.15",
4
4
  "description": "Job Manager 2 - A simple yet powerful job scheduler combining cron and at functionality",
5
5
  "type": "module",
6
6
  "main": "src/cli/index.js",
@@ -501,7 +501,7 @@ class WindowsService extends PlatformService {
501
501
  const dataDir = getDataDir();
502
502
 
503
503
  const wrapper = `@echo off
504
- set JM2_DATA_DIR=${dataDir}
504
+ set "JM2_DATA_DIR=${dataDir}"
505
505
  "${nodePath}" "${jm2Path}" start
506
506
  `;
507
507
 
@@ -521,6 +521,13 @@ set JM2_DATA_DIR=${dataDir}
521
521
  // Create wrapper script
522
522
  const wrapperPath = this.getWrapperPath();
523
523
  const wrapper = this.generateWrapper();
524
+
525
+ // Ensure the data directory exists before writing the wrapper
526
+ const dir = dirname(wrapperPath);
527
+ if (!existsSync(dir)) {
528
+ mkdirSync(dir, { recursive: true });
529
+ }
530
+
524
531
  writeFileSync(wrapperPath, wrapper, 'utf8');
525
532
 
526
533
  // Install service using sc.exe
@@ -133,7 +133,21 @@ export class Scheduler {
133
133
  // Calculate next run time for active jobs
134
134
  let nextRun = null;
135
135
  if (job.status === JobStatus.ACTIVE) {
136
- nextRun = this.calculateNextRun(job, new Date());
136
+ // Check if there's a stored nextRun that is in the past (missed execution)
137
+ const storedNextRun = job.nextRun || job.nextRunISO;
138
+ if (storedNextRun) {
139
+ const storedDate = new Date(storedNextRun);
140
+ const now = new Date();
141
+ // If stored nextRun is in the past and it's a cron job, keep it so tick() will detect it as overdue
142
+ if (storedDate < now && job.type === JobType.CRON) {
143
+ nextRun = storedDate;
144
+ }
145
+ }
146
+
147
+ // If nextRun wasn't set from stored value, calculate a new one
148
+ if (!nextRun) {
149
+ nextRun = this.calculateNextRun(job, new Date());
150
+ }
137
151
  }
138
152
 
139
153
  this.jobs.set(job.id, {
@@ -360,8 +374,9 @@ export class Scheduler {
360
374
  this.logger.info(`Executing overdue job ${jobId} (${job.name || 'unnamed'})`);
361
375
  // Execute immediately without waiting for the normal due jobs check
362
376
  this.executeJob(job);
363
- // Update next run time from now for the next scheduled occurrence
364
- const nextRun = this.calculateNextRun(job, nowDate);
377
+ // Calculate next run from the original scheduled time to maintain cadence
378
+ const originalNextRun = job.nextRun ? new Date(job.nextRun) : new Date();
379
+ const nextRun = this.calculateNextRunAfterExecution(job, originalNextRun);
365
380
  this.updateJobNextRun(jobId, nextRun);
366
381
  }
367
382
  }
@@ -581,6 +596,14 @@ export class Scheduler {
581
596
  ...job,
582
597
  nextRun: job.nextRun ? job.nextRun.toISOString() : null,
583
598
  }));
599
+
600
+ // Safety check: don't persist empty jobs array if we had jobs before
601
+ // This prevents accidental data loss during startup/shutdown
602
+ if (jobsArray.length === 0 && this.jobs.size > 0) {
603
+ this.logger.error('BUG: Attempted to save empty jobs array but jobs Map is not empty!');
604
+ return;
605
+ }
606
+
584
607
  saveJobs(jobsArray);
585
608
  }
586
609