Package Exports
- @ooneex/cron
- @ooneex/cron/package.json
Readme
@ooneex/cron
A scheduled task runner and cron job management library for TypeScript applications with timezone support. This package provides an abstract base class for creating scheduled jobs with a human-readable time syntax and seamless integration with the Ooneex framework.
Features
✅ Human-Readable Syntax - Define schedules with intuitive syntax like "every 1 hours"
✅ Timezone Support - Run jobs in specific timezones using IANA timezone names
✅ Start/Stop Control - Programmatically start and stop scheduled jobs
✅ Active Status - Check if a job is currently running
✅ Container Integration - Works seamlessly with dependency injection
✅ Type-Safe - Full TypeScript support with proper type definitions
✅ Error Handling - Comprehensive error handling with custom exceptions
Installation
Bun
bun add @ooneex/cronpnpm
pnpm add @ooneex/cronYarn
yarn add @ooneex/cronnpm
npm install @ooneex/cronUsage
Basic Cron Job
import { Cron, type CronTimeType } from '@ooneex/cron';
import type { TimeZoneType } from '@ooneex/country';
class CleanupCron extends Cron {
public getTime(): CronTimeType {
return 'every 1 hours';
}
public getTimeZone(): TimeZoneType | null {
return null; // Use server's local timezone
}
public async job(): Promise<void> {
console.log('Running cleanup task...');
// Cleanup logic here
}
}
// Start the cron job
const cleanup = new CleanupCron();
await cleanup.start();With Timezone Support
import { Cron, type CronTimeType } from '@ooneex/cron';
import type { TimeZoneType } from '@ooneex/country';
class DailyReportCron extends Cron {
public getTime(): CronTimeType {
return 'every 24 hours';
}
public getTimeZone(): TimeZoneType | null {
return 'Europe/Paris'; // Run at Paris time
}
public async job(): Promise<void> {
await this.generateDailyReport();
await this.sendReportEmail();
}
private async generateDailyReport(): Promise<void> {
// Report generation logic
}
private async sendReportEmail(): Promise<void> {
// Email sending logic
}
}Different Time Intervals
import { Cron, type CronTimeType } from '@ooneex/cron';
// Every 30 seconds
class FrequentCheckCron extends Cron {
public getTime(): CronTimeType {
return 'every 30 seconds';
}
public getTimeZone(): null {
return null;
}
public async job(): Promise<void> {
console.log('Checking...');
}
}
// Every 5 minutes
class CacheRefreshCron extends Cron {
public getTime(): CronTimeType {
return 'every 5 minutes';
}
public getTimeZone(): null {
return null;
}
public async job(): Promise<void> {
await this.refreshCache();
}
}
// Every 7 days (weekly)
class WeeklyBackupCron extends Cron {
public getTime(): CronTimeType {
return 'every 7 days';
}
public getTimeZone(): TimeZoneType | null {
return 'America/New_York';
}
public async job(): Promise<void> {
await this.performBackup();
}
}Controlling Cron Jobs
import { Cron } from '@ooneex/cron';
const job = new MyCronJob();
// Start the job
await job.start();
console.log('Job is active:', job.isActive()); // true
// Stop the job
await job.stop();
console.log('Job is active:', job.isActive()); // false
// Restart the job
await job.start();API Reference
Classes
Cron (Abstract)
Abstract base class for creating scheduled jobs.
Abstract Methods to Implement:
getTime(): CronTimeType
Returns the schedule timing for the job.
Returns: A string in the format "every N units" or "in N units"
Example:
public getTime(): CronTimeType {
return 'every 1 hours';
}getTimeZone(): TimeZoneType | null
Returns the timezone for the job schedule.
Returns: IANA timezone string or null for server's local timezone
Example:
public getTimeZone(): TimeZoneType | null {
return 'Europe/London';
}job(): Promise<void>
The task to execute on schedule.
Example:
public async job(): Promise<void> {
await this.performTask();
}Inherited Methods:
start(): Promise<void>
Starts the cron job. If already active, does nothing.
Throws: CronException if the job fails to start
Example:
const job = new MyCronJob();
await job.start();stop(): Promise<void>
Stops the cron job.
Example:
await job.stop();isActive(): boolean
Checks if the cron job is currently running.
Returns: true if the job is active, false otherwise
Example:
if (job.isActive()) {
console.log('Job is running');
}Types
CronTimeType
String format for defining job schedules.
type CronTimeType = `${PrefixType} ${number} ${SuffixType}`;Examples:
'every 1 seconds''every 30 seconds''every 5 minutes''every 1 hours''every 24 hours''every 7 days''every 1 months''every 1 years''in 10 seconds''in 5 minutes'
PrefixType
type PrefixType = 'in' | 'every';SuffixType
type SuffixType = 'seconds' | 'minutes' | 'hours' | 'days' | 'months' | 'years';CronClassType
type CronClassType = new (...args: any[]) => ICron;Enums
ECronPrefix
| Value | Description |
|---|---|
IN |
Run once after specified time |
EVERY |
Run repeatedly at specified interval |
ECronSuffix
| Value | Description |
|---|---|
SECONDS |
Time in seconds |
MINUTES |
Time in minutes |
HOURS |
Time in hours |
DAYS |
Time in days |
MONTHS |
Time in months |
YEARS |
Time in years |
Interfaces
ICron
interface ICron {
getTime: () => Promise<CronTimeType> | CronTimeType;
start: () => Promise<void> | void;
stop: () => Promise<void> | void;
job: () => Promise<void> | void;
getTimeZone: () => TimeZoneType | null;
isActive: () => Promise<boolean> | boolean;
}Advanced Usage
Integration with Ooneex App
import { App } from '@ooneex/app';
import { CleanupCron, BackupCron, ReportCron } from './cron';
const app = new App({
cronJobs: [CleanupCron, BackupCron, ReportCron],
// ... other config
});
await app.run();
// All cron jobs are automatically startedUsing Container Decorators
import { Cron, decorator, type CronTimeType } from '@ooneex/cron';
import { container } from '@ooneex/container';
@decorator.cron()
class EmailQueueCron extends Cron {
public getTime(): CronTimeType {
return 'every 1 minutes';
}
public getTimeZone(): null {
return null;
}
public async job(): Promise<void> {
await this.processEmailQueue();
}
}
// Job is automatically registered with container
const job = container.get(EmailQueueCron);
await job.start();Error Handling
import { Cron, CronException, type CronTimeType } from '@ooneex/cron';
class RiskyJob extends Cron {
public getTime(): CronTimeType {
return 'every 5 minutes';
}
public getTimeZone(): null {
return null;
}
public async job(): Promise<void> {
try {
await this.riskyOperation();
} catch (error) {
console.error('Job failed:', error);
// Handle error without crashing the scheduler
}
}
}
// Handle startup errors
try {
const job = new RiskyJob();
await job.start();
} catch (error) {
if (error instanceof CronException) {
console.error('Failed to start cron job:', error.message);
}
}Conditional Job Execution
import { Cron, type CronTimeType } from '@ooneex/cron';
class ConditionalCron extends Cron {
private enabled = true;
public getTime(): CronTimeType {
return 'every 1 hours';
}
public getTimeZone(): null {
return null;
}
public async job(): Promise<void> {
if (!this.enabled) {
console.log('Job skipped - disabled');
return;
}
await this.performTask();
}
public enable(): void {
this.enabled = true;
}
public disable(): void {
this.enabled = false;
}
}Job with Logging
import { Cron, type CronTimeType } from '@ooneex/cron';
import { container } from '@ooneex/container';
import type { ILogger } from '@ooneex/logger';
class LoggingCron extends Cron {
private readonly logger = container.get<ILogger>('logger');
public getTime(): CronTimeType {
return 'every 30 minutes';
}
public getTimeZone(): TimeZoneType | null {
return 'UTC';
}
public async job(): Promise<void> {
this.logger.info('Cron job started', { job: 'LoggingCron' });
try {
await this.performTask();
this.logger.success('Cron job completed', { job: 'LoggingCron' });
} catch (error) {
this.logger.error('Cron job failed', {
job: 'LoggingCron',
error: error instanceof Error ? error.message : String(error)
});
}
}
}Multiple Jobs with Shared Resources
import { Cron, type CronTimeType } from '@ooneex/cron';
import { container } from '@ooneex/container';
import type { ICache } from '@ooneex/cache';
import type { IDatabase } from '@ooneex/database';
abstract class BaseCron extends Cron {
protected readonly cache = container.get<ICache>('cache');
protected readonly database = container.get<IDatabase>('database');
}
class CacheWarmupCron extends BaseCron {
public getTime(): CronTimeType {
return 'every 15 minutes';
}
public getTimeZone(): null {
return null;
}
public async job(): Promise<void> {
const data = await this.database.query('SELECT * FROM hot_data');
await this.cache.set('hot_data', data, 900); // 15 min TTL
}
}
class DataCleanupCron extends BaseCron {
public getTime(): CronTimeType {
return 'every 1 days';
}
public getTimeZone(): TimeZoneType | null {
return 'UTC';
}
public async job(): Promise<void> {
await this.database.query('DELETE FROM logs WHERE created_at < NOW() - INTERVAL 30 DAY');
await this.cache.delete('old_cache_key');
}
}License
This project is licensed under the MIT License - see the LICENSE file for details.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
Development Setup
- Clone the repository
- Install dependencies:
bun install - Run tests:
bun run test - Build the project:
bun run build
Guidelines
- Write tests for new features
- Follow the existing code style
- Update documentation for API changes
- Ensure all tests pass before submitting PR
Made with ❤️ by the Ooneex team