@gravito/horizon 3.0.1 → 3.2.0

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/index.d.ts CHANGED
@@ -2,65 +2,136 @@ import { CacheManager } from '@gravito/stasis';
2
2
  import { ActionCallback, Logger, HookManager, GravitoOrbit, PlanetCore } from '@gravito/core';
3
3
 
4
4
  /**
5
- * Advanced cron expression parser with fallback support.
5
+ * High-performance cron expression evaluator with LRU caching and fallback support.
6
+ *
7
+ * Employs a tiered strategy for cron evaluation:
8
+ * 1. Cache: O(1) lookup for high-frequency checks.
9
+ * 2. Simple Parser: Lightweight evaluator for standard expressions.
10
+ * 3. Advanced Parser: Dynamic import of `cron-parser` for complex expressions.
11
+ *
12
+ * @internal
6
13
  */
7
14
  declare class CronParser {
15
+ private static cache;
16
+ /** Cache duration in milliseconds (1 minute). */
17
+ private static readonly CACHE_TTL;
18
+ /** Maximum number of unique expression/timezone combinations to store. */
19
+ private static readonly MAX_CACHE_SIZE;
8
20
  /**
9
- * Get the next execution date based on a cron expression.
21
+ * Calculates the next occurrence of a cron expression.
22
+ *
23
+ * Dynamically loads `cron-parser` to minimize initial bundle size and memory footprint.
24
+ *
25
+ * @param expression - Valid 5-part cron expression.
26
+ * @param timezone - Target timezone for evaluation (default: "UTC").
27
+ * @param currentDate - Reference time to calculate from (default: now).
28
+ * @returns Resolves to the next execution Date object.
29
+ * @throws {Error} If the expression format is invalid.
30
+ *
31
+ * @example
32
+ * ```typescript
33
+ * const next = await CronParser.nextDate('0 0 * * *');
34
+ * ```
10
35
  */
11
36
  static nextDate(expression: string, timezone?: string, currentDate?: Date): Promise<Date>;
12
37
  /**
13
- * Check if the cron expression is due to run at the current time (minute precision).
38
+ * Determines if a task is due for execution at the specified time.
39
+ *
40
+ * Uses minute-precision caching to optimize repeated evaluations within
41
+ * the same scheduling window. Implements LRU eviction to maintain memory efficiency.
42
+ *
43
+ * @param expression - Cron expression to evaluate.
44
+ * @param timezone - Execution timezone.
45
+ * @param currentDate - Reference time for the check.
46
+ * @returns True if the expression matches the reference time.
14
47
  */
15
48
  static isDue(expression: string, timezone?: string, currentDate?: Date): Promise<boolean>;
49
+ /**
50
+ * Internal logic for tiered cron evaluation.
51
+ *
52
+ * @param expression - Cron expression.
53
+ * @param timezone - Target timezone.
54
+ * @param currentDate - Current time.
55
+ * @returns Boolean indicating if the task is due.
56
+ *
57
+ * @internal
58
+ */
59
+ private static computeIsDue;
60
+ /**
61
+ * Evicts the oldest entry from the cache when capacity is reached.
62
+ *
63
+ * @internal
64
+ */
65
+ private static cleanupCache;
66
+ /**
67
+ * Purges all entries from the internal cache.
68
+ * Useful for testing or when global timezone settings change.
69
+ */
70
+ static clearCache(): void;
71
+ /**
72
+ * Compares two dates with minute precision.
73
+ *
74
+ * @internal
75
+ */
16
76
  private static minuteMatches;
17
77
  }
18
78
 
19
79
  /**
20
- * Interface for distributed lock storage backends.
80
+ * Contract for distributed lock storage backends.
21
81
  *
22
- * Provides methods for acquiring, releasing, and managing
23
- * distributed locks to prevent concurrent task execution.
82
+ * Defines the essential operations required to manage mutual exclusion across
83
+ * multiple scheduler instances. Implementations must ensure atomicity for
84
+ * distributed safety.
24
85
  *
25
86
  * @public
26
87
  * @since 3.0.0
27
88
  */
28
89
  interface LockStore {
29
90
  /**
30
- * Attempt to acquire a lock
31
- * @param key The lock key
32
- * @param ttlSeconds Time to live in seconds
33
- * @returns true if lock acquired, false if lock already exists
91
+ * Attempts to acquire a mutex lock for a specific key.
92
+ *
93
+ * Must be atomic. If the key is already locked, it should return false
94
+ * immediately without blocking.
95
+ *
96
+ * @param key - The unique lock identifier.
97
+ * @param ttlSeconds - Expiration duration in seconds to prevent deadlocks.
98
+ * @returns True if the lock was successfully acquired.
34
99
  */
35
100
  acquire(key: string, ttlSeconds: number): Promise<boolean>;
36
101
  /**
37
- * Release a lock
38
- * @param key The lock key
102
+ * Explicitly releases a held lock.
103
+ *
104
+ * Should be idempotent; releasing a non-existent lock should not throw.
105
+ *
106
+ * @param key - The lock identifier to remove.
39
107
  */
40
108
  release(key: string): Promise<void>;
41
109
  /**
42
- * Force acquire a lock (overwrite existing)
43
- * @param key The lock key
44
- * @param ttlSeconds Time to live in seconds
110
+ * Forcibly acquires or refreshes a lock, overwriting any existing state.
111
+ *
112
+ * @param key - The lock identifier.
113
+ * @param ttlSeconds - New expiration duration.
45
114
  */
46
115
  forceAcquire(key: string, ttlSeconds: number): Promise<void>;
47
116
  /**
48
- * Check if a lock exists
49
- * @param key The lock key
117
+ * Checks if a lock is currently active and not expired.
118
+ *
119
+ * @param key - The lock identifier.
120
+ * @returns True if the lock exists.
50
121
  */
51
122
  exists(key: string): Promise<boolean>;
52
123
  }
53
124
 
54
125
  /**
55
- * Cache-based lock store using Gravito Stasis.
126
+ * Distributed lock implementation backed by Gravito Stasis.
56
127
  *
57
- * Stores locks in the cache system for distributed locking
58
- * across multiple application instances.
128
+ * Leverages the shared cache system (Redis, Memcached, etc.) to provide
129
+ * atomic locking across multiple application nodes.
59
130
  *
60
131
  * @example
61
132
  * ```typescript
62
- * const store = new CacheLockStore(cacheManager, 'locks:')
63
- * const acquired = await store.acquire('task-123', 300)
133
+ * const store = new CacheLockStore(cacheManager);
134
+ * const locked = await store.acquire('nightly-sync', 600);
64
135
  * ```
65
136
  *
66
137
  * @since 3.0.0
@@ -69,37 +140,61 @@ interface LockStore {
69
140
  declare class CacheLockStore implements LockStore {
70
141
  private cache;
71
142
  private prefix;
143
+ /**
144
+ * Initializes the store with a cache manager.
145
+ *
146
+ * @param cache - The Stasis cache instance.
147
+ * @param prefix - Key prefix to avoid collisions in the shared namespace.
148
+ */
72
149
  constructor(cache: CacheManager, prefix?: string);
150
+ /**
151
+ * Computes the fully qualified cache key.
152
+ *
153
+ * @internal
154
+ */
73
155
  private getKey;
156
+ /**
157
+ * Atomic 'add' operation ensures only one node succeeds.
158
+ *
159
+ * @param key - Lock key.
160
+ * @param ttlSeconds - Expiration.
161
+ */
74
162
  acquire(key: string, ttlSeconds: number): Promise<boolean>;
163
+ /**
164
+ * Removes the lock key from cache.
165
+ *
166
+ * @param key - Lock key.
167
+ */
75
168
  release(key: string): Promise<void>;
169
+ /**
170
+ * Overwrites the lock key, effectively resetting the TTL.
171
+ *
172
+ * @param key - Lock key.
173
+ * @param ttlSeconds - New expiration.
174
+ */
76
175
  forceAcquire(key: string, ttlSeconds: number): Promise<void>;
176
+ /**
177
+ * Validates if the lock key is present in the cache.
178
+ *
179
+ * @param key - Lock key.
180
+ */
77
181
  exists(key: string): Promise<boolean>;
78
182
  }
79
183
 
80
184
  /**
81
- * Manager for distributed locks to prevent concurrent task execution.
185
+ * Orchestrator for distributed locks to prevent concurrent task execution.
82
186
  *
83
- * Supports multiple storage backends (memory, cache, custom) and provides
84
- * a unified interface for acquiring and releasing locks.
187
+ * Implements a pluggable storage pattern, allowing the scheduler to operate
188
+ * in both single-node (Memory) and multi-node (Cache/Redis) environments.
189
+ * Provides a unified interface for safe lock acquisition and release.
85
190
  *
86
191
  * @example
87
192
  * ```typescript
88
- * // Using memory store
89
- * const locks = new LockManager('memory')
90
- *
91
- * // Using cache store
92
- * const locks = new LockManager('cache', { cache: cacheManager })
93
- *
94
- * // Acquire a lock
95
- * const acquired = await locks.acquire('task:send-emails', 300)
96
- * if (acquired) {
97
- * try {
98
- * // Execute task
99
- * } finally {
100
- * await locks.release('task:send-emails')
101
- * }
102
- * }
193
+ * // Production setup with distributed cache
194
+ * const locks = new LockManager('cache', { cache: cacheManager });
195
+ *
196
+ * // Attempt to acquire a mutex lock for 5 minutes
197
+ * const acquired = await locks.acquire('task:db-backup', 300);
103
198
  * ```
104
199
  *
105
200
  * @since 3.0.0
@@ -107,81 +202,202 @@ declare class CacheLockStore implements LockStore {
107
202
  */
108
203
  declare class LockManager {
109
204
  private store;
205
+ /**
206
+ * Initializes the manager with a specific storage driver.
207
+ *
208
+ * @param driver - Strategy identifier or a custom `LockStore` implementation.
209
+ * @param context - Dependencies required by certain drivers (e.g., CacheManager).
210
+ * @throws {Error} If 'cache' driver is selected but no `CacheManager` is provided.
211
+ */
110
212
  constructor(driver: 'memory' | 'cache' | LockStore, context?: {
111
213
  cache?: CacheManager;
112
214
  });
215
+ /**
216
+ * Attempts to acquire a lock. Fails if the key is already locked.
217
+ *
218
+ * @param key - Unique identifier for the lock.
219
+ * @param ttlSeconds - Time-to-live in seconds before the lock expires.
220
+ * @returns True if the lock was successfully acquired.
221
+ */
113
222
  acquire(key: string, ttlSeconds: number): Promise<boolean>;
223
+ /**
224
+ * Explicitly releases a held lock.
225
+ *
226
+ * @param key - The lock identifier to remove.
227
+ * @returns Resolves when the lock is deleted.
228
+ */
114
229
  release(key: string): Promise<void>;
230
+ /**
231
+ * Forcibly acquires or overwrites an existing lock.
232
+ *
233
+ * Used for execution locks where the latest attempt should take precedence
234
+ * if the previous one is deemed expired.
235
+ *
236
+ * @param key - Lock identifier.
237
+ * @param ttlSeconds - Expiration duration.
238
+ */
115
239
  forceAcquire(key: string, ttlSeconds: number): Promise<void>;
240
+ /**
241
+ * Checks if a specific lock currently exists and is not expired.
242
+ *
243
+ * @param key - Lock identifier.
244
+ * @returns True if the key is locked and active.
245
+ */
116
246
  exists(key: string): Promise<boolean>;
117
247
  }
118
248
 
119
249
  /**
120
- * In-memory lock store for single-instance deployments.
250
+ * Lightweight, in-memory lock store for local development and single-node deployments.
121
251
  *
122
- * Stores locks in memory with automatic expiration.
123
- * Not suitable for multi-instance deployments.
252
+ * Implements the `LockStore` contract using a local `Map`. It does not support
253
+ * shared state across processes or servers.
124
254
  *
125
255
  * @example
126
256
  * ```typescript
127
- * const store = new MemoryLockStore()
128
- * const acquired = await store.acquire('task-123', 300)
129
- * if (acquired) {
130
- * // Execute task
131
- * await store.release('task-123')
132
- * }
257
+ * const store = new MemoryLockStore();
258
+ * const ok = await store.acquire('local-job', 60);
133
259
  * ```
134
260
  *
135
261
  * @since 3.0.0
136
262
  * @public
137
263
  */
138
264
  declare class MemoryLockStore implements LockStore {
265
+ /** Map of lock keys to their expiration timestamps (ms). */
139
266
  private locks;
267
+ /**
268
+ * Acquires a local lock if the key is not already active.
269
+ *
270
+ * @param key - Lock identifier.
271
+ * @param ttlSeconds - Expiration duration.
272
+ */
140
273
  acquire(key: string, ttlSeconds: number): Promise<boolean>;
274
+ /**
275
+ * Deletes the lock from local memory.
276
+ *
277
+ * @param key - Lock identifier.
278
+ */
141
279
  release(key: string): Promise<void>;
280
+ /**
281
+ * Sets or overwrites a local lock.
282
+ *
283
+ * @param key - Lock identifier.
284
+ * @param ttlSeconds - Expiration.
285
+ */
142
286
  forceAcquire(key: string, ttlSeconds: number): Promise<void>;
287
+ /**
288
+ * Checks if a local lock is present and hasn't expired.
289
+ *
290
+ * Automatically purges expired locks upon checking.
291
+ *
292
+ * @param key - Lock identifier.
293
+ */
143
294
  exists(key: string): Promise<boolean>;
144
295
  }
145
296
 
146
297
  /**
147
- * Represents a configuration for a scheduled task (Cron job).
298
+ * Represents the configuration and state of a scheduled task.
299
+ *
300
+ * Encapsulates all metadata required by the scheduler to evaluate frequency,
301
+ * manage distributed locking, and execute task logic with reliability controls.
148
302
  *
149
303
  * @public
150
304
  * @since 3.0.0
151
305
  */
152
306
  interface ScheduledTask {
153
- /** Unique name for the task */
307
+ /**
308
+ * Unique identifier for the task.
309
+ * Used for logging, hook identification, and as part of the lock key.
310
+ */
154
311
  name: string;
155
- /** Standard cron expression mapping the frequency */
312
+ /**
313
+ * Standard 5-part cron expression defining execution frequency.
314
+ * Format: "minute hour day month weekday"
315
+ */
156
316
  expression: string;
157
- /** Timezone for evaluating the cron expression (default: UTC) */
317
+ /**
318
+ * Timezone identifier for evaluating the cron expression.
319
+ * @defaultValue "UTC"
320
+ */
158
321
  timezone: string;
159
- /** The function or task to execute */
322
+ /**
323
+ * The asynchronous task logic to be executed.
324
+ */
160
325
  callback: () => void | Promise<void>;
161
- /** If true, uses a distributed lock to ensure only one server runs the task */
326
+ /**
327
+ * Whether to ensure single-point execution across a distributed environment.
328
+ * When true, uses a time-window lock to prevent multiple servers from running
329
+ * the same task in the same scheduling window.
330
+ */
162
331
  shouldRunOnOneServer: boolean;
163
- /** Time-to-live for the distributed lock in seconds (default: 300) */
332
+ /**
333
+ * Duration in seconds to hold the distributed time-window lock.
334
+ * @defaultValue 300
335
+ */
164
336
  lockTtl: number;
165
- /** If true, the task runs in the background and doesn't block the scheduler loop */
337
+ /**
338
+ * Whether to execute the task in a non-blocking background mode.
339
+ * If true, the scheduler won't wait for completion before processing the next task.
340
+ */
166
341
  background: boolean;
167
- /** Optional node role required to run this task (e.g., 'worker') */
342
+ /**
343
+ * Optional target node role required for execution.
344
+ * Tasks will only run if the current node matches this role.
345
+ */
168
346
  nodeRole?: string;
169
- /** Command string if the task was registered via a shell command */
347
+ /**
348
+ * Raw shell command if the task was created via `scheduler.exec()`.
349
+ */
170
350
  command?: string;
171
- /** Callbacks executed after successful task completion */
351
+ /**
352
+ * Maximum execution time in milliseconds before the task is aborted.
353
+ * @defaultValue 3600000
354
+ */
355
+ timeout?: number;
356
+ /**
357
+ * Number of times to retry a failed task.
358
+ * @defaultValue 0
359
+ */
360
+ retries?: number;
361
+ /**
362
+ * Delay between retry attempts in milliseconds.
363
+ * @defaultValue 1000
364
+ */
365
+ retryDelay?: number;
366
+ /**
367
+ * Whether to prevent concurrent executions of the same task.
368
+ * If true, a new instance won't start if the previous one is still running.
369
+ */
370
+ preventOverlapping: boolean;
371
+ /**
372
+ * Maximum duration in seconds for the execution lock.
373
+ * Prevents deadlocks if a task crashes without releasing the lock.
374
+ * @defaultValue 3600
375
+ */
376
+ overlappingExpiresAt: number;
377
+ /**
378
+ * Collection of callbacks executed upon successful task completion.
379
+ */
172
380
  onSuccessCallbacks: ActionCallback[];
173
- /** Callbacks executed after task failure */
381
+ /**
382
+ * Collection of callbacks executed when the task fails after all retries.
383
+ */
174
384
  onFailureCallbacks: ActionCallback[];
175
385
  }
176
386
  /**
177
- * Fluent API for defining task schedules.
387
+ * Fluent builder for defining and configuring scheduled tasks.
388
+ *
389
+ * Provides a human-readable API for setting execution frequency, constraints,
390
+ * reliability settings, and lifecycle hooks.
178
391
  *
179
392
  * @example
180
393
  * ```typescript
181
- * scheduler.task('backup')
182
- * .daily()
183
- * .at('02:00')
184
- * .onOneServer();
394
+ * scheduler.task('backup-db', async () => {
395
+ * await db.backup();
396
+ * })
397
+ * .dailyAt('03:00')
398
+ * .onOneServer()
399
+ * .withoutOverlapping()
400
+ * .retry(3, 5000);
185
401
  * ```
186
402
  *
187
403
  * @public
@@ -190,188 +406,259 @@ interface ScheduledTask {
190
406
  declare class TaskSchedule {
191
407
  private task;
192
408
  /**
193
- * Create a new TaskSchedule instance.
409
+ * Initializes a new schedule instance with default settings.
194
410
  *
195
- * @param name - The unique name of the task.
196
- * @param callback - The function to execute.
411
+ * @param name - Unique task name used for identification and locking.
412
+ * @param callback - Logic to execute on schedule.
197
413
  */
198
414
  constructor(name: string, callback: () => void | Promise<void>);
199
415
  /**
200
- * Set a custom cron expression.
416
+ * Configures a raw 5-part cron expression.
417
+ *
418
+ * @param expression - Cron string (e.g., "0 0 * * *").
419
+ * @returns The TaskSchedule instance for chaining.
420
+ * @throws {Error} If expression format is invalid or contains forbidden characters.
201
421
  *
202
- * @param expression - Standard cron expression (e.g., "* * * * *")
203
- * @returns The TaskSchedule instance.
422
+ * @example
423
+ * ```typescript
424
+ * schedule.cron('0 9-17 * * 1-5'); // 9-5 on weekdays
425
+ * ```
204
426
  */
205
427
  cron(expression: string): this;
206
428
  /**
207
- * Run the task every minute.
429
+ * Schedules execution every minute.
208
430
  *
209
- * @returns The TaskSchedule instance.
431
+ * @returns The TaskSchedule instance for chaining.
210
432
  */
211
433
  everyMinute(): this;
212
434
  /**
213
- * Run the task every 5 minutes.
435
+ * Schedules execution every five minutes.
214
436
  *
215
- * @returns The TaskSchedule instance.
437
+ * @returns The TaskSchedule instance for chaining.
216
438
  */
217
439
  everyFiveMinutes(): this;
218
440
  /**
219
- * Run the task every 10 minutes.
441
+ * Schedules execution every ten minutes.
220
442
  *
221
- * @returns The TaskSchedule instance.
443
+ * @returns The TaskSchedule instance for chaining.
222
444
  */
223
445
  everyTenMinutes(): this;
224
446
  /**
225
- * Run the task every 15 minutes.
447
+ * Schedules execution every fifteen minutes.
226
448
  *
227
- * @returns The TaskSchedule instance.
449
+ * @returns The TaskSchedule instance for chaining.
228
450
  */
229
451
  everyFifteenMinutes(): this;
230
452
  /**
231
- * Run the task every 30 minutes.
453
+ * Schedules execution every thirty minutes.
232
454
  *
233
- * @returns The TaskSchedule instance.
455
+ * @returns The TaskSchedule instance for chaining.
234
456
  */
235
457
  everyThirtyMinutes(): this;
236
458
  /**
237
- * Run the task hourly (at minute 0).
459
+ * Schedules execution hourly at the top of the hour.
238
460
  *
239
- * @returns The TaskSchedule instance.
461
+ * @returns The TaskSchedule instance for chaining.
240
462
  */
241
463
  hourly(): this;
242
464
  /**
243
- * Run the task hourly at a specific minute.
465
+ * Schedules execution hourly at a specific minute.
244
466
  *
245
- * @param minute - Minute (0-59)
246
- * @returns The TaskSchedule instance.
467
+ * @param minute - Target minute (0-59).
468
+ * @returns The TaskSchedule instance for chaining.
469
+ * @throws {Error} If minute is outside 0-59 range.
247
470
  */
248
471
  hourlyAt(minute: number): this;
249
472
  /**
250
- * Run the task daily at midnight (00:00).
473
+ * Schedules execution daily at midnight.
251
474
  *
252
- * @returns The TaskSchedule instance.
475
+ * @returns The TaskSchedule instance for chaining.
253
476
  */
254
477
  daily(): this;
255
478
  /**
256
- * Run the task daily at a specific time.
479
+ * Schedules execution daily at a specific time.
257
480
  *
258
- * @param time - Time in "HH:mm" format (24h)
259
- * @returns The TaskSchedule instance.
481
+ * @param time - 24-hour time string in "HH:mm" format.
482
+ * @returns The TaskSchedule instance for chaining.
483
+ * @throws {Error} If time format is invalid or values are out of range.
484
+ *
485
+ * @example
486
+ * ```typescript
487
+ * schedule.dailyAt('14:30');
488
+ * ```
260
489
  */
261
490
  dailyAt(time: string): this;
262
491
  /**
263
- * Run the task weekly on Sunday at midnight.
492
+ * Schedules execution weekly on Sunday at midnight.
264
493
  *
265
- * @returns The TaskSchedule instance.
494
+ * @returns The TaskSchedule instance for chaining.
266
495
  */
267
496
  weekly(): this;
268
497
  /**
269
- * Run the task weekly on a specific day and time.
498
+ * Schedules execution weekly on a specific day and time.
499
+ *
500
+ * @param day - Day index (0-6, where 0 is Sunday).
501
+ * @param time - Optional 24-hour time string "HH:mm" (default "00:00").
502
+ * @returns The TaskSchedule instance for chaining.
503
+ * @throws {Error} If day index or time format is invalid.
270
504
  *
271
- * @param day - Day of week (0-7, 0 or 7 is Sunday)
272
- * @param time - Time in "HH:mm" format (default "00:00")
273
- * @returns The TaskSchedule instance.
505
+ * @example
506
+ * ```typescript
507
+ * schedule.weeklyOn(1, '09:00'); // Mondays at 9 AM
508
+ * ```
274
509
  */
275
510
  weeklyOn(day: number, time?: string): this;
276
511
  /**
277
- * Run the task monthly on the 1st day at midnight.
512
+ * Schedules execution monthly on the first day at midnight.
278
513
  *
279
- * @returns The TaskSchedule instance.
514
+ * @returns The TaskSchedule instance for chaining.
280
515
  */
281
516
  monthly(): this;
282
517
  /**
283
- * Run the task monthly on a specific day and time.
518
+ * Schedules execution monthly on a specific day and time.
284
519
  *
285
- * @param day - Day of month (1-31)
286
- * @param time - Time in "HH:mm" format (default "00:00")
287
- * @returns The TaskSchedule instance.
520
+ * @param day - Day of month (1-31).
521
+ * @param time - Optional 24-hour time string "HH:mm" (default "00:00").
522
+ * @returns The TaskSchedule instance for chaining.
523
+ * @throws {Error} If day or time format is invalid.
288
524
  */
289
525
  monthlyOn(day: number, time?: string): this;
290
526
  /**
291
- * Set the timezone for the task execution.
527
+ * Specifies the timezone for evaluating schedule frequency.
292
528
  *
293
- * @param timezone - Timezone identifier (e.g., "Asia/Taipei", "UTC")
294
- * @returns The TaskSchedule instance.
529
+ * @param timezone - IANA timezone identifier (e.g., "America/New_York").
530
+ * @returns The TaskSchedule instance for chaining.
531
+ * @throws {Error} If the timezone identifier is not recognized by the system.
295
532
  */
296
533
  timezone(timezone: string): this;
297
534
  /**
298
- * Set the time of execution for the current frequency.
299
- * Useful when chaining with daily(), weekly(), etc.
535
+ * Modifies the execution time of the existing frequency.
536
+ * Typically used after frequency methods like daily() or weekly().
300
537
  *
301
- * @param time - Time in "HH:mm" format
302
- * @returns The TaskSchedule instance.
538
+ * @param time - 24-hour time string in "HH:mm" format.
539
+ * @returns The TaskSchedule instance for chaining.
540
+ * @throws {Error} If time format is invalid.
303
541
  */
304
542
  at(time: string): this;
305
543
  /**
306
- * Ensure task runs on only one server at a time (Distributed Locking).
307
- * Requires a configured LockStore (Cache or Redis).
544
+ * Enables distributed locking to ensure only one instance runs globally.
545
+ * Prevents duplicate execution when multiple servers are polling the same schedule.
308
546
  *
309
- * @param lockTtlSeconds - Time in seconds to hold the lock (default 300)
310
- * @returns The TaskSchedule instance.
547
+ * @param lockTtlSeconds - Duration in seconds to hold the window lock (default 300).
548
+ * @returns The TaskSchedule instance for chaining.
311
549
  */
312
550
  onOneServer(lockTtlSeconds?: number): this;
313
551
  /**
314
- * Alias for onOneServer.
315
- * Prevents overlapping executions of the same task.
552
+ * Prevents a new task instance from starting if the previous one is still running.
316
553
  *
317
- * @param expiresAt - Lock TTL in seconds
318
- * @returns The TaskSchedule instance.
554
+ * Unlike `onOneServer()` which uses a time-window lock, this uses an execution lock
555
+ * to handle long-running tasks that might span multiple scheduling intervals.
556
+ *
557
+ * @param expiresAt - Max duration in seconds to keep the execution lock (default 3600).
558
+ * @returns The TaskSchedule instance for chaining.
559
+ *
560
+ * @example
561
+ * ```typescript
562
+ * // Prevents overlapping if the heavy operation takes > 1 minute
563
+ * scheduler.task('data-sync', heavySync)
564
+ * .everyMinute()
565
+ * .withoutOverlapping();
566
+ * ```
319
567
  */
320
568
  withoutOverlapping(expiresAt?: number): this;
321
569
  /**
322
- * Run task in background (do not wait for completion in the loop).
323
- * Note: In Node.js non-blocking environment this is largely semantic,
324
- * but affects how we handle error catching and lock release.
570
+ * Executes the task in background mode.
571
+ * The scheduler will not wait for this task to finish before proceeding to the next.
325
572
  *
326
- * @returns The TaskSchedule instance.
573
+ * @returns The TaskSchedule instance for chaining.
327
574
  */
328
575
  runInBackground(): this;
329
576
  /**
330
- * Restrict task execution to a specific node role.
577
+ * Restricts task execution to nodes with a specific role.
331
578
  *
332
- * @param role - The required node role (e.g., 'api', 'worker')
333
- * @returns The TaskSchedule instance.
579
+ * @param role - Target role identifier (e.g., "worker").
580
+ * @returns The TaskSchedule instance for chaining.
334
581
  */
335
582
  onNode(role: string): this;
336
583
  /**
337
- * Set the command string for exec tasks.
584
+ * Defines a maximum execution time for the task.
585
+ *
586
+ * @param ms - Timeout duration in milliseconds.
587
+ * @returns The TaskSchedule instance for chaining.
588
+ * @throws {Error} If timeout is not a positive number.
589
+ */
590
+ timeout(ms: number): this;
591
+ /**
592
+ * Configures automatic retry behavior for failed executions.
593
+ *
594
+ * @param attempts - Max number of retries (default 3).
595
+ * @param delayMs - Wait time between retries in milliseconds (default 1000).
596
+ * @returns The TaskSchedule instance for chaining.
597
+ * @throws {Error} If attempts or delay are negative.
598
+ */
599
+ retry(attempts?: number, delayMs?: number): this;
600
+ /**
601
+ * Sets the shell command for execution-based tasks.
338
602
  *
339
603
  * @param command - The command string.
340
- * @returns The TaskSchedule instance.
604
+ * @returns The TaskSchedule instance for chaining.
341
605
  * @internal
342
606
  */
343
607
  setCommand(command: string): this;
344
608
  /**
345
- * Register a callback to run on task success.
609
+ * Registers a callback to execute upon successful task completion.
346
610
  *
347
- * @param callback - The callback function.
348
- * @returns The TaskSchedule instance.
611
+ * @param callback - Function to run on success.
612
+ * @returns The TaskSchedule instance for chaining.
349
613
  */
350
614
  onSuccess(callback: ActionCallback): this;
351
615
  /**
352
- * Register a callback to run on task failure.
616
+ * Registers a callback to execute when the task fails.
353
617
  *
354
- * @param callback - The callback function.
355
- * @returns The TaskSchedule instance.
618
+ * @param callback - Function to run on failure.
619
+ * @returns The TaskSchedule instance for chaining.
356
620
  */
357
621
  onFailure(callback: ActionCallback): this;
358
622
  /**
359
- * Set a description for the task (useful for listing).
623
+ * Attaches a human-readable description to the task.
360
624
  *
361
- * @param _text - The description text.
362
- * @returns The TaskSchedule instance.
625
+ * @param _text - Description text.
626
+ * @returns The TaskSchedule instance for chaining.
363
627
  */
364
628
  description(_text: string): this;
365
629
  /**
366
- * Get the underlying task configuration.
630
+ * Returns the final task configuration.
367
631
  *
368
- * @returns The ScheduledTask object.
632
+ * @returns The constructed ScheduledTask object.
369
633
  */
370
634
  getTask(): ScheduledTask;
371
635
  }
372
636
 
373
637
  /**
374
- * Core Scheduler Manager responsible for managing and executing tasks.
638
+ * Central registry and execution engine for scheduled tasks.
639
+ *
640
+ * Orchestrates the lifecycle of scheduled jobs by evaluating frequencies,
641
+ * managing distributed locks to prevent duplicate execution, and handling
642
+ * reliability features like retries and timeouts.
643
+ *
644
+ * Architecture Principles:
645
+ * - Distributed Safety: Uses lock keys scoped to minute precision for global deduplication.
646
+ * - Non-blocking: Executes tasks in parallel using fire-and-forget patterns.
647
+ * - Observability: Emits granular lifecycle hooks for monitoring and alerting.
648
+ *
649
+ * @example
650
+ * ```typescript
651
+ * const scheduler = new SchedulerManager(lockManager, logger, hooks, 'worker');
652
+ *
653
+ * // Define a maintenance task
654
+ * scheduler.task('daily-cleanup', async () => {
655
+ * await db.cleanup();
656
+ * })
657
+ * .dailyAt('03:00')
658
+ * .onOneServer();
659
+ * ```
660
+ *
661
+ * @public
375
662
  */
376
663
  declare class SchedulerManager {
377
664
  lockManager: LockManager;
@@ -379,80 +666,153 @@ declare class SchedulerManager {
379
666
  private hooks?;
380
667
  private currentNodeRole?;
381
668
  private tasks;
669
+ /**
670
+ * Initializes the scheduler engine.
671
+ *
672
+ * @param lockManager - Backend for distributed locking.
673
+ * @param logger - Optional logger for operational visibility.
674
+ * @param hooks - Optional manager for lifecycle event hooks.
675
+ * @param currentNodeRole - Role identifier for the local node (used for filtering).
676
+ */
382
677
  constructor(lockManager: LockManager, logger?: Logger | undefined, hooks?: HookManager | undefined, currentNodeRole?: string | undefined);
383
678
  /**
384
- * Define a new scheduled task.
679
+ * Registers a new callback-based scheduled task.
680
+ *
681
+ * @param name - Unique task name used for identification and locking.
682
+ * @param callback - Asynchronous function containing the task logic.
683
+ * @returns A fluent TaskSchedule instance for further configuration.
385
684
  *
386
- * @param name - Unique name for the task
387
- * @param callback - Function to execute
388
- * @returns The newly created TaskSchedule.
685
+ * @example
686
+ * ```typescript
687
+ * scheduler.task('process-queues', async () => {
688
+ * await queue.process();
689
+ * }).everyMinute();
690
+ * ```
389
691
  */
390
692
  task(name: string, callback: () => void | Promise<void>): TaskSchedule;
391
693
  /**
392
- * Define a new scheduled command execution task.
694
+ * Registers a shell command as a scheduled task.
393
695
  *
394
- * @param name - Unique name for the task
395
- * @param command - Shell command to execute
396
- * @returns The newly created TaskSchedule.
696
+ * Executes the command via `sh -c` on matching nodes.
697
+ *
698
+ * @param name - Unique identifier for the command task.
699
+ * @param command - Raw shell command string.
700
+ * @returns A fluent TaskSchedule instance.
701
+ * @throws {Error} If the shell command returns a non-zero exit code during execution.
702
+ *
703
+ * @example
704
+ * ```typescript
705
+ * scheduler.exec('log-rotate', 'logrotate /etc/logrotate.conf')
706
+ * .daily()
707
+ * .onNode('worker');
708
+ * ```
397
709
  */
398
710
  exec(name: string, command: string): TaskSchedule;
399
711
  /**
400
- * Add a pre-configured task schedule object.
712
+ * Injects a pre-configured TaskSchedule instance into the registry.
401
713
  *
402
- * @param schedule - The task schedule to add.
714
+ * @param schedule - Configured task schedule to register.
403
715
  */
404
716
  add(schedule: TaskSchedule): void;
405
717
  /**
406
- * Get all registered task definitions.
718
+ * Exports all registered tasks for external inspection or serialization.
407
719
  *
408
- * @returns An array of scheduled tasks.
720
+ * @returns An array of raw task configurations.
409
721
  */
410
722
  getTasks(): ScheduledTask[];
411
723
  /**
412
- * Trigger the scheduler to check and run due tasks.
413
- * This is typically called every minute by a system cron or worker loop.
724
+ * Main evaluation loop that triggers tasks due for execution.
725
+ *
726
+ * Should be invoked every minute by a system timer (systemd/cron) or daemon.
727
+ * Performs frequency checks, role filtering, and parallel execution.
414
728
  *
415
- * @param date - The current reference date (default: now)
416
- * @returns A promise that resolves when the scheduler run is complete.
729
+ * @param date - Reference time for cron evaluation (default: current time).
730
+ * @returns Resolves when all due tasks have been initiated.
417
731
  */
418
732
  run(date?: Date): Promise<void>;
419
733
  /**
420
- * Execute a specific task with locking logic.
734
+ * Executes an individual task after validating execution constraints.
735
+ *
736
+ * Evaluates node roles, overlapping prevention, and distributed time-window locks
737
+ * before initiating the actual task logic.
738
+ *
739
+ * @param task - Target task configuration.
740
+ * @param date - Reference time used for lock key generation.
421
741
  *
422
- * @param task - The task to execute.
423
742
  * @internal
424
743
  */
425
744
  runTask(task: ScheduledTask, date?: Date): Promise<void>;
426
745
  /**
427
- * Execute the task callback and handle hooks.
746
+ * Internal wrapper for executing task logic with reliability controls.
428
747
  *
429
- * @param task - The task to execute.
748
+ * Handles timeouts, retries, and emits lifecycle hooks for monitoring.
749
+ *
750
+ * @param task - The scheduled task to execute.
751
+ * @returns Resolves when the task (and its retries) completes or fails permanently.
752
+ *
753
+ * @internal
430
754
  */
431
755
  private executeTask;
432
756
  }
433
757
 
434
758
  /**
435
- * OrbitHorizon is the official Task Scheduler for Gravito.
436
- * It provides a fluent API for defining Cron jobs that can run on a schedule,
437
- * with support for distributed locking (run on one server) and node roles.
759
+ * Enterprise task scheduler orbit enabling distributed cron-based job execution.
760
+ *
761
+ * Provides the infrastructure for defining scheduled tasks with distributed locking,
762
+ * preventing duplicate execution across multi-server deployments. Integrates seamlessly
763
+ * with Gravito's orbit system to expose the scheduler in both the IoC container and
764
+ * request context.
765
+ *
766
+ * Design rationale: Uses pluggable lock backends (memory/cache) to support both
767
+ * development (single-node) and production (multi-node) environments without code changes.
438
768
  *
439
769
  * @example
770
+ * Single-node development setup:
440
771
  * ```typescript
441
- * const horizon = new OrbitHorizon();
442
- * core.addOrbit(horizon);
772
+ * await PlanetCore.boot({
773
+ * config: {
774
+ * scheduler: {
775
+ * lock: { driver: 'memory' }
776
+ * }
777
+ * },
778
+ * orbits: [OrbitHorizon]
779
+ * })
780
+ * ```
443
781
  *
444
- * // Defining a task
445
- * const scheduler = core.container.make('scheduler');
446
- * scheduler.call('cleanup', async () => { ... }).daily().at('03:00').onOneServer();
782
+ * @example
783
+ * Multi-node production with distributed locking:
784
+ * ```typescript
785
+ * import { OrbitCache } from '@gravito/stasis'
786
+ *
787
+ * await PlanetCore.boot({
788
+ * config: {
789
+ * scheduler: {
790
+ * lock: { driver: 'cache' },
791
+ * nodeRole: 'worker'
792
+ * }
793
+ * },
794
+ * orbits: [
795
+ * OrbitCache, // Must load before Horizon
796
+ * OrbitHorizon
797
+ * ]
798
+ * })
447
799
  * ```
800
+ *
448
801
  * @public
449
802
  */
450
803
  declare class OrbitHorizon implements GravitoOrbit {
451
804
  /**
452
- * Install the Horizon Orbit into PlanetCore.
453
- * Registers the SchedulerManager and configures the distributed lock driver.
805
+ * Integrates the Horizon scheduler into the PlanetCore lifecycle.
454
806
  *
455
- * @param core - The PlanetCore instance.
807
+ * Orchestrates the initialization sequence:
808
+ * 1. Resolves lock backend (memory or cache-based).
809
+ * 2. Instantiates SchedulerManager with global dependencies (logger, hooks).
810
+ * 3. Registers the scheduler in the IoC container for CLI and global access.
811
+ * 4. Injects the scheduler into the request context via middleware.
812
+ *
813
+ * @param core - PlanetCore instance providing configuration and service container.
814
+ *
815
+ * @throws {Error} If the cache driver is explicitly requested but `CacheManager` is unavailable.
456
816
  */
457
817
  install(core: PlanetCore): void;
458
818
  }
@@ -464,51 +824,66 @@ declare module '@gravito/core' {
464
824
  }
465
825
 
466
826
  /**
467
- * Result of a process execution.
827
+ * Encapsulates the outcome of a child process execution.
828
+ *
829
+ * Provides status codes and captured stream outputs for programmatic inspection.
468
830
  *
469
831
  * @public
470
832
  * @since 3.0.0
471
833
  */
472
834
  interface ProcessResult {
473
- /** Exit code of the process (0 indicates success). */
835
+ /** numeric exit code returned by the operating system (0 typically denotes success). */
474
836
  exitCode: number;
475
- /** Standard output from the process. */
837
+ /** Captured UTF-8 encoded text from the standard output stream. */
476
838
  stdout: string;
477
- /** Standard error output from the process. */
839
+ /** Captured UTF-8 encoded text from the standard error stream. */
478
840
  stderr: string;
479
- /** Whether the process completed successfully (exitCode === 0). */
841
+ /** Semantic indicator of successful completion (mapped from exitCode === 0). */
480
842
  success: boolean;
481
843
  }
482
844
  /**
483
- * Execute a shell command and capture its output.
845
+ * Spawns a shell command and asynchronously captures its full output.
846
+ *
847
+ * Leverages the Gravito runtime adapter to ensure compatibility across different
848
+ * JavaScript runtimes (Bun, Node.js). Executes commands within a shell (`sh -c`)
849
+ * to support pipes, redirects, and environment variables.
850
+ *
851
+ * @param command - Raw shell command string to execute.
852
+ * @returns Resolves to a detailed `ProcessResult` object.
484
853
  *
485
- * @param command - The command string to execute.
486
- * @returns A promise that resolves to the process result.
854
+ * @example
855
+ * ```typescript
856
+ * const result = await runProcess('ls -lh /var/logs');
857
+ * if (result.success) {
858
+ * processLogs(result.stdout);
859
+ * }
860
+ * ```
487
861
  *
488
862
  * @public
489
863
  * @since 3.0.0
490
864
  */
491
865
  declare function runProcess(command: string): Promise<ProcessResult>;
492
866
  /**
493
- * Process execution utility for running shell commands.
867
+ * Utility class for managing child process lifecycles.
494
868
  *
495
- * Provides a simple interface for executing shell commands
496
- * and capturing their output.
869
+ * Acts as a wrapper for `runProcess` to maintain compatibility with earlier
870
+ * versions of the framework.
497
871
  *
498
872
  * @example
499
873
  * ```typescript
500
- * const result = await Process.run('ls -la')
501
- * if (result.success) {
502
- * console.log(result.stdout)
503
- * } else {
504
- * console.error(result.stderr)
505
- * }
874
+ * const { stdout } = await Process.run('bun -v');
506
875
  * ```
507
876
  *
508
877
  * @since 3.0.0
509
878
  * @public
510
879
  */
511
880
  declare class Process {
881
+ /**
882
+ * Static alias for `runProcess`.
883
+ *
884
+ * @param command - Command to execute.
885
+ * @returns Process outcome.
886
+ */
512
887
  static run(command: string): Promise<ProcessResult>;
513
888
  }
514
889