cronius
Version:
A flexible, powerful cron job orchestrator for Node.js – jobs, retries, dependencies, monitoring
359 lines (285 loc) • 9.92 kB
Markdown
# Cronius
A flexible, powerful cron job orchestrator for Node.js with advanced features including job dependencies, retry mechanisms, parallel execution, and comprehensive monitoring.
## Features
- **Flexible Scheduling**: Standard cron syntax, human-readable expressions, and one-time execution
- **Job Orchestration**: Sequential chains, parallel execution groups, and conditional job execution
- **Retry & Error Handling**: Configurable retry attempts with linear or exponential backoff
- **Dependencies**: Job dependency management ensuring proper execution order
- **Monitoring**: Real-time metrics, event emission, and Prometheus integration
- **TypeScript**: Full TypeScript support with comprehensive type definitions
- **CLI Interface**: Built-in command-line tool for job management
## Installation
```bash
npm install cronius
```
## Quick Start
### Basic Usage
```typescript
import Cronius from 'cronius';
// Create a Cronius instance
const cronius = new Cronius({
timezone: 'America/New_York',
defaultRetryAttempts: 3,
});
// Create a simple job
const backupJob = cronius.createJob({
id: 'backup-database',
name: 'Database Backup',
description: 'Daily database backup at 2 AM',
schedule: '0 2 * * *', // Every day at 2:00 AM
handler: async (job) => {
console.log(`Starting backup job: ${job.id}`);
// Your backup logic here
return { status: 'completed', timestamp: new Date() };
},
retryAttempts: 3,
retryDelay: 5000,
retryBackoff: 'exponential',
});
// Start the job
await backupJob.start();
```
### Human-Readable Schedules
```typescript
// Run every 5 minutes
const frequentJob = cronius.createJob({
id: 'frequent-task',
schedule: { every: 5, unit: 'minute' },
handler: async () => console.log('Frequent task executed'),
});
// Run every hour at 9:00 AM
const hourlyJob = cronius.createJob({
id: 'hourly-task',
schedule: { every: 1, unit: 'hour', at: '9:00 AM' },
handler: async () => console.log('Hourly task executed'),
});
// Run every week on Monday
const weeklyJob = cronius.createJob({
id: 'weekly-task',
schedule: { every: 1, unit: 'week', at: '9:00 AM' },
handler: async () => console.log('Weekly task executed'),
});
```
### One-Time Execution
```typescript
// Run once at a specific time
const oneTimeJob = cronius.createJob({
id: 'one-time-task',
schedule: new Date('2024-01-01T00:00:00Z'),
handler: async () => console.log('One-time task executed'),
});
```
### Job Dependencies
```typescript
// Create jobs with dependencies
const dataJob = cronius.createJob({
id: 'fetch-data',
schedule: '0 * * * *', // Every hour
handler: async () => {
// Fetch data logic
return { data: 'processed' };
},
});
const reportJob = cronius.createJob({
id: 'generate-report',
schedule: '0 2 * * *', // Daily at 2 AM
dependencies: ['fetch-data'], // Wait for data job to complete
handler: async (job) => {
// Generate report using data from fetch-data job
return { report: 'generated' };
},
});
```
### Parallel Execution Groups
```typescript
// Set up orchestrator for complex workflows
const orchestrator = cronius.setupOrchestrator({
jobs: [dataJob, reportJob],
parallelGroups: [
['job1', 'job2'], // These jobs run in parallel
['job3', 'job4'], // These also run in parallel
],
sequentialChains: [
['group1', 'group2'], // group2 waits for group1 to complete
],
});
// Execute parallel group
await orchestrator.executeParallelGroup(0);
```
### Event Handling
```typescript
// Listen to job events
const events = cronius.getEvents();
events.on('job-start', (event) => {
console.log(`Job ${event.jobId} started at ${event.timestamp}`);
});
events.on('job-success', (event) => {
console.log(`Job ${event.jobId} completed successfully`);
});
events.on('job-fail', (event) => {
console.log(`Job ${event.jobId} failed:`, event.data?.error);
});
events.on('job-retry', (event) => {
console.log(`Job ${event.data.jobId} retrying (attempt ${event.data.attempt})`);
});
```
### Error Handling and Retries
```typescript
const resilientJob = cronius.createJob({
id: 'resilient-task',
schedule: '*/5 * * * *', // Every 5 minutes
handler: async (job) => {
// Your task logic here
if (Math.random() < 0.3) {
throw new Error('Random failure');
}
return 'success';
},
retryAttempts: 5,
retryDelay: 1000,
retryBackoff: 'exponential',
onError: async (error, job) => {
console.error(`Job ${job.id} failed after retries:`, error.message);
// Send notification, log to external service, etc.
},
onSuccess: async (result, job) => {
console.log(`Job ${job.id} completed successfully:`, result);
},
});
```
### Metrics and Monitoring
```typescript
// Get system metrics
const metrics = cronius.getMetrics();
const overallMetrics = metrics.getOverallMetrics();
console.log(`Total jobs: ${overallMetrics.totalJobs}`);
console.log(`Success rate: ${overallMetrics.successRate.toFixed(2)}%`);
console.log(`Average execution time: ${overallMetrics.averageExecutionTime}ms`);
// Get job-specific metrics
const jobMetrics = metrics.getJobMetrics('backup-database');
console.log(`Job executions: ${jobMetrics.executions}`);
console.log(`Job failures: ${jobMetrics.failures}`);
// Export Prometheus metrics
const prometheusMetrics = metrics.getPrometheusMetrics();
console.log(prometheusMetrics);
```
## CLI Usage
Cronius includes a built-in command-line interface for job management:
```bash
# List all jobs
npx cronius list
# Start a specific job
npx cronius start backup-database
# Stop a running job
npx cronius stop backup-database
# Show job status
npx cronius status backup-database
# Show system metrics
npx cronius metrics
# Create a demo job
npx cronius create demo-job "0 * * * *"
# Get help
npx cronius help
```
## Configuration Options
### Cronius Configuration
```typescript
interface CroniusConfig {
timezone?: string; // Default: 'UTC'
maxConcurrentJobs?: number; // Default: 10
defaultRetryAttempts?: number; // Default: 3
defaultRetryDelay?: number; // Default: 1000ms
retryBackoff?: 'linear' | 'exponential'; // Default: 'exponential'
prometheusMetrics?: boolean; // Default: false
logger?: Logger; // Custom logger implementation
}
```
### Job Configuration
```typescript
interface JobConfig {
id: string; // Required: Unique job identifier
name?: string; // Optional: Human-readable name
description?: string; // Optional: Job description
schedule: string | Date | HumanSchedule; // Required: Execution schedule
handler: JobHandler; // Required: Job execution function
retryAttempts?: number; // Default: 3
retryDelay?: number; // Default: 1000ms
retryBackoff?: 'linear' | 'exponential'; // Default: 'exponential'
timeout?: number; // Optional: Execution timeout in ms
dependencies?: string[]; // Optional: Job dependencies
runCondition?: (job: Job) => boolean | Promise<boolean>; // Optional: Conditional execution
onSuccess?: (result: any, job: Job) => void | Promise<void>; // Optional: Success callback
onError?: (error: Error, job: Job) => void | Promise<void>; // Optional: Error callback
metadata?: Record<string, any>; // Optional: Custom metadata
}
```
## Advanced Features
### Conditional Job Execution
```typescript
const conditionalJob = cronius.createJob({
id: 'conditional-task',
schedule: '0 * * * *',
handler: async () => 'conditional execution',
runCondition: async (job) => {
// Only run if certain conditions are met
const shouldRun = await checkSomeCondition();
return shouldRun;
},
});
```
### Custom Logging
```typescript
import winston from 'winston';
const logger = winston.createLogger({
level: 'info',
format: winston.format.json(),
transports: [new winston.transports.Console()],
});
const cronius = new Cronius({
logger: {
info: (message, meta) => logger.info(message, meta),
warn: (message, meta) => logger.warn(message, meta),
error: (message, meta) => logger.error(message, meta),
debug: (message, meta) => logger.debug(message, meta),
},
});
```
### Timezone Support
```typescript
const cronius = new Cronius({
timezone: 'America/New_York',
});
// All schedules will be interpreted in the specified timezone
const eastCoastJob = cronius.createJob({
id: 'east-coast-job',
schedule: '0 9 * * 1-5', // 9 AM Eastern, weekdays only
handler: async () => console.log('East coast business hours'),
});
```
## API Reference
### Core Classes
- **Cronius**: Main orchestrator class
- **Job**: Individual job instance
- **Orchestrator**: Complex workflow management
- **MetricsCollector**: Performance monitoring
- **Scheduler**: Schedule parsing and calculation
- **RetryManager**: Retry logic and backoff strategies
### Events
- `job-start`: Job execution begins
- `job-success`: Job completes successfully
- `job-fail`: Job fails (before retries)
- `job-retry`: Job retry attempt
- `job-complete`: Job execution ends (any status)
- `orchestration-start`: Workflow execution begins
- `orchestration-complete`: Workflow execution ends
- `orchestration-error`: Workflow execution error
## Contributing
Contributions are welcome! Please read our contributing guidelines and ensure all tests pass before submitting a pull request.
## License
MIT License - see [LICENSE](LICENSE) file for details.
## Support
- **Issues**: [GitHub Issues](https://github.com/txkachi/cronius/issues)
- **Documentation**: [GitHub Wiki](https://github.com/txkachi/cronius/wiki)
- **Discussions**: [GitHub Discussions](https://github.com/txkachi/cronius/discussions)
## Changelog
See [CHANGELOG.md](CHANGELOG.md) for a detailed history of changes.