@veloxts/scheduler 0.6.107 → 0.7.1

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
@@ -1,6 +1,6 @@
1
1
  # @veloxts/scheduler
2
2
 
3
- > **Early Access (v0.6.x)**
3
+ > **Early Access (v0.7.x)**
4
4
 
5
5
  Cron-based task scheduling for VeloxTS Framework - provides a fluent API for defining recurring tasks with overlap prevention and timezone support. Learn more at [@veloxts/velox](https://www.npmjs.com/package/@veloxts/velox).
6
6
 
package/dist/manager.js CHANGED
@@ -3,6 +3,7 @@
3
3
  *
4
4
  * Core scheduler that manages and executes scheduled tasks.
5
5
  */
6
+ import { createLogger } from '@veloxts/core';
6
7
  import { CronJob } from 'cron';
7
8
  /**
8
9
  * Maximum execution history entries per task.
@@ -38,7 +39,7 @@ const DEFAULT_MAX_LOCK_MINUTES = 1440;
38
39
  * ```
39
40
  */
40
41
  export function createScheduler(tasks, options = {}) {
41
- const { timezone: defaultTimezone = 'UTC', debug = false } = options;
42
+ const { timezone: defaultTimezone = 'UTC' } = options;
42
43
  // Job states
43
44
  const jobs = new Map();
44
45
  // Execution history - use per-task arrays for O(1) trimming instead of O(n²)
@@ -56,14 +57,7 @@ export function createScheduler(tasks, options = {}) {
56
57
  let running = false;
57
58
  // Track running task promises for graceful shutdown
58
59
  const runningTasks = new Map();
59
- /**
60
- * Log debug message.
61
- */
62
- function log(message) {
63
- if (debug) {
64
- console.log(`[scheduler] ${message}`);
65
- }
66
- }
60
+ const log = createLogger('scheduler');
67
61
  /**
68
62
  * Add execution to history.
69
63
  * O(1) amortized - uses per-task arrays with simple shift for trimming.
@@ -107,7 +101,7 @@ export function createScheduler(tasks, options = {}) {
107
101
  const lockExpired = jobState.runningStartedAt && Date.now() - jobState.runningStartedAt.getTime() > maxLockMs;
108
102
  if (lockExpired) {
109
103
  // Lock expired - force release and allow new execution
110
- log(`Lock expired for ${task.name} after ${task.maxLockMinutes ?? DEFAULT_MAX_LOCK_MINUTES} minutes, forcing new execution`);
104
+ log.debug(`Lock expired for ${task.name} after ${task.maxLockMinutes ?? DEFAULT_MAX_LOCK_MINUTES} minutes, forcing new execution`);
111
105
  jobState.isRunning = false;
112
106
  jobState.runningStartedAt = undefined;
113
107
  }
@@ -117,7 +111,7 @@ export function createScheduler(tasks, options = {}) {
117
111
  execution.status = 'skipped';
118
112
  execution.completedAt = new Date();
119
113
  execution.duration = 0;
120
- log(`Skipping ${task.name}: ${skipReason}`);
114
+ log.debug(`Skipping ${task.name}: ${skipReason}`);
121
115
  if (task.onSkip) {
122
116
  try {
123
117
  await task.onSkip(ctx, skipReason);
@@ -147,7 +141,7 @@ export function createScheduler(tasks, options = {}) {
147
141
  execution.status = 'skipped';
148
142
  execution.completedAt = new Date();
149
143
  execution.duration = 0;
150
- log(`Skipping ${task.name}: ${skipReason}`);
144
+ log.debug(`Skipping ${task.name}: ${skipReason}`);
151
145
  if (task.onSkip) {
152
146
  try {
153
147
  await task.onSkip(ctx, skipReason);
@@ -173,7 +167,7 @@ export function createScheduler(tasks, options = {}) {
173
167
  execution.status = 'skipped';
174
168
  execution.completedAt = new Date();
175
169
  execution.duration = 0;
176
- log(`Skipping ${task.name}: ${skipReason}`);
170
+ log.debug(`Skipping ${task.name}: ${skipReason}`);
177
171
  addToHistory(execution);
178
172
  return execution;
179
173
  }
@@ -181,7 +175,7 @@ export function createScheduler(tasks, options = {}) {
181
175
  // Mark as running
182
176
  jobState.isRunning = true;
183
177
  jobState.runningStartedAt = new Date();
184
- log(`Starting ${task.name}`);
178
+ log.debug(`Starting ${task.name}`);
185
179
  if (options.onTaskStart) {
186
180
  try {
187
181
  await options.onTaskStart(task, ctx);
@@ -216,7 +210,7 @@ export function createScheduler(tasks, options = {}) {
216
210
  execution.completedAt = completedAt;
217
211
  execution.duration = duration;
218
212
  jobState.lastRunAt = completedAt;
219
- log(`Completed ${task.name} in ${duration}ms`);
213
+ log.debug(`Completed ${task.name} in ${duration}ms`);
220
214
  if (task.onSuccess) {
221
215
  try {
222
216
  await task.onSuccess(ctx, duration);
@@ -242,7 +236,7 @@ export function createScheduler(tasks, options = {}) {
242
236
  execution.completedAt = completedAt;
243
237
  execution.duration = duration;
244
238
  execution.error = errorObj.message;
245
- log(`Failed ${task.name}: ${errorObj.message}`);
239
+ log.debug(`Failed ${task.name}: ${errorObj.message}`);
246
240
  if (task.onFailure) {
247
241
  try {
248
242
  await task.onFailure(ctx, errorObj, duration);
@@ -273,7 +267,7 @@ export function createScheduler(tasks, options = {}) {
273
267
  function initializeJobs() {
274
268
  for (const task of tasks) {
275
269
  if (!task.enabled) {
276
- log(`Skipping disabled task: ${task.name}`);
270
+ log.debug(`Skipping disabled task: ${task.name}`);
277
271
  continue;
278
272
  }
279
273
  const taskTimezone = task.timezone || defaultTimezone;
@@ -283,7 +277,7 @@ export function createScheduler(tasks, options = {}) {
283
277
  // Track the running promise for graceful shutdown
284
278
  const taskPromise = executeTask(jobState)
285
279
  .catch((err) => {
286
- console.error(`[scheduler] Unhandled error in ${task.name}:`, err);
280
+ log.error(`Unhandled error in ${task.name}:`, err);
287
281
  // Return a failed execution to satisfy the type
288
282
  return {
289
283
  taskName: task.name,
@@ -308,7 +302,7 @@ export function createScheduler(tasks, options = {}) {
308
302
  isRunning: false,
309
303
  };
310
304
  jobs.set(task.name, jobState);
311
- log(`Registered task: ${task.name} (${task.cronExpression})`);
305
+ log.debug(`Registered task: ${task.name} (${task.cronExpression})`);
312
306
  }
313
307
  }
314
308
  // Initialize jobs
@@ -316,21 +310,21 @@ export function createScheduler(tasks, options = {}) {
316
310
  const manager = {
317
311
  start() {
318
312
  if (running) {
319
- log('Scheduler already running');
313
+ log.debug('Scheduler already running');
320
314
  return;
321
315
  }
322
316
  running = true;
323
- log('Starting scheduler');
317
+ log.debug('Starting scheduler');
324
318
  for (const jobState of jobs.values()) {
325
319
  jobState.cronJob.start();
326
320
  }
327
321
  },
328
322
  async stop() {
329
323
  if (!running) {
330
- log('Scheduler not running');
324
+ log.debug('Scheduler not running');
331
325
  return;
332
326
  }
333
- log('Stopping scheduler');
327
+ log.debug('Stopping scheduler');
334
328
  // Stop all cron jobs (prevents new executions)
335
329
  for (const jobState of jobs.values()) {
336
330
  jobState.cronJob.stop();
@@ -340,10 +334,10 @@ export function createScheduler(tasks, options = {}) {
340
334
  const maxWait = 30000; // 30 seconds
341
335
  const runningPromises = Array.from(runningTasks.values());
342
336
  if (runningPromises.length > 0) {
343
- log(`Waiting for ${runningPromises.length} running task(s) to complete...`);
337
+ log.debug(`Waiting for ${runningPromises.length} running task(s) to complete...`);
344
338
  const timeoutPromise = new Promise((resolve) => {
345
339
  setTimeout(() => {
346
- log('Graceful shutdown timeout reached, forcing stop');
340
+ log.debug('Graceful shutdown timeout reached, forcing stop');
347
341
  resolve();
348
342
  }, maxWait);
349
343
  });
@@ -352,7 +346,7 @@ export function createScheduler(tasks, options = {}) {
352
346
  }
353
347
  running = false;
354
348
  runningTasks.clear();
355
- log('Scheduler stopped');
349
+ log.debug('Scheduler stopped');
356
350
  },
357
351
  isRunning() {
358
352
  return running;
@@ -376,7 +370,7 @@ export function createScheduler(tasks, options = {}) {
376
370
  if (!jobState) {
377
371
  throw new Error(`Task not found: ${name}`);
378
372
  }
379
- log(`Manually running task: ${name}`);
373
+ log.debug(`Manually running task: ${name}`);
380
374
  return executeTask(jobState);
381
375
  },
382
376
  getNextRun(name) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@veloxts/scheduler",
3
- "version": "0.6.107",
3
+ "version": "0.7.1",
4
4
  "description": "Task scheduling for VeloxTS framework",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -20,13 +20,13 @@
20
20
  "dependencies": {
21
21
  "cron": "4.4.0",
22
22
  "fastify-plugin": "5.1.0",
23
- "@veloxts/core": "0.6.107"
23
+ "@veloxts/core": "0.7.1"
24
24
  },
25
25
  "peerDependencies": {
26
26
  "fastify": "^5.7.4"
27
27
  },
28
28
  "devDependencies": {
29
- "@types/node": "25.1.0",
29
+ "@types/node": "25.2.3",
30
30
  "@vitest/coverage-v8": "4.0.18",
31
31
  "fastify": "5.7.4",
32
32
  "typescript": "5.9.3",