
Research
/Security News
Popular Tinycolor npm Package Compromised in Supply Chain Attack Affecting 40+ Packages
Malicious update to @ctrl/tinycolor on npm is part of a supply-chain attack hitting 40+ packages across maintainers
@plus99/cronx
Advanced tools
A reliable, distributed-ready cron job scheduler for Node.js designed as a drop-in replacement for node-cron.
npm install @plus99/cronx
import { Cronx } from '@plus99/cronx';
// Create scheduler with in-memory storage
const cronx = new Cronx({
storage: 'memory://',
workerId: 'my-worker'
});
// Schedule a job
await cronx.schedule('*/5 * * * * *', async () => {
console.log('Job executed every 5 seconds!');
return { status: 'success' };
}, {
name: 'my-job',
retries: 3,
timeout: 10000
});
// Start the scheduler
await cronx.start();
const cronx = new Cronx({ storage: 'memory://' });
const cronx = new Cronx({ storage: 'sqlite://./jobs.db' });
const cronx = new Cronx({
storage: 'postgresql://user:password@localhost:5432/cronx'
});
const cronx = new Cronx({ storage: 'redis://localhost:6379' });
await cronx.schedule('0 9 * * 1', jobFunction, {
name: 'weekly-report',
retries: 5,
backoff: 'exponential',
timeout: 30000,
onSuccess: (result) => console.log('Success:', result),
onError: (error) => console.error('Failed:', error)
});
name
- Unique job identifierretries
- Number of retry attempts (default: 0)backoff
- Retry strategy: 'fixed' or 'exponential' (default: 'fixed')timeout
- Job timeout in milliseconds (default: 30000)onSuccess
- Success callback functiononError
- Error callback function// Pause a job
await cronx.pauseJob('my-job');
// Resume a job
await cronx.resumeJob('my-job');
// Run a job immediately
await cronx.runJob('my-job');
// Remove a job
await cronx.unschedule('my-job');
// Get job details
const job = await cronx.getJob('my-job');
// List all jobs
const jobs = await cronx.listJobs();
// Get overall statistics
const stats = await cronx.getStats();
console.log(stats);
// { totalJobs: 5, activeJobs: 3, pausedJobs: 2, isRunning: true }
// Get job-specific statistics
const jobStats = await cronx.getJobStats('my-job');
console.log(jobStats);
// { totalRuns: 100, successfulRuns: 95, failedRuns: 5, averageDuration: 1250 }
// Get job execution history
const runs = await cronx.getJobRuns('my-job', 10);
console.log(runs);
Enable metrics collection for monitoring:
const cronx = new Cronx({
storage: 'redis://localhost:6379',
metrics: true
});
// Get metrics in Prometheus format
const metrics = await cronx.getMetrics();
Available metrics:
cronx_jobs_total
- Total number of scheduled jobscronx_job_executions_total
- Total job executions by statuscronx_job_duration_seconds
- Job execution duration histogramcronx_active_jobs
- Currently active jobs gaugeCronx supports both standard 5-field and extended 6-field cron expressions:
// Standard format (minute hour day month weekday)
'0 9 * * 1' // Every Monday at 9:00 AM
'*/15 * * * *' // Every 15 minutes
// Extended format with seconds (second minute hour day month weekday)
'*/30 * * * * *' // Every 30 seconds
'0 0 12 * * 1-5' // Weekdays at noon
try {
await cronx.schedule('invalid-cron', async () => {});
} catch (error) {
console.error('Invalid cron expression:', error.message);
}
// Job-level error handling
await cronx.schedule('*/5 * * * *', async () => {
// Job might fail
if (Math.random() > 0.8) {
throw new Error('Random failure');
}
return { success: true };
}, {
name: 'failing-job',
retries: 3,
onError: (error, attempt) => {
console.log(`Attempt ${attempt} failed:`, error.message);
}
});
When running multiple Cronx instances with shared storage, distributed locking ensures only one instance executes each job:
// Worker 1
const worker1 = new Cronx({
storage: 'postgresql://localhost/cronx',
workerId: 'worker-1'
});
// Worker 2
const worker2 = new Cronx({
storage: 'postgresql://localhost/cronx',
workerId: 'worker-2'
});
// Both schedule the same job - only one will execute at a time
await worker1.schedule('*/1 * * * *', jobFunction, { name: 'shared-job' });
await worker2.schedule('*/1 * * * *', jobFunction, { name: 'shared-job' });
new Cronx(options: CronxOptions)
start()
- Start the schedulerstop()
- Stop the schedulerschedule(schedule, handler, options)
- Schedule a new jobunschedule(name)
- Remove a jobpauseJob(name)
- Pause a jobresumeJob(name)
- Resume a jobrunJob(name)
- Execute a job immediatelygetJob(name)
- Get job detailslistJobs()
- List all jobsgetStats()
- Get system statisticsgetJobStats(name?)
- Get job statisticsgetJobRuns(name, limit?)
- Get job execution historygetMetrics()
- Get Prometheus metricsMIT License - see LICENSE file for details.
FAQs
Reliable Cron for Node.js
We found that @plus99/cronx demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
/Security News
Malicious update to @ctrl/tinycolor on npm is part of a supply-chain attack hitting 40+ packages across maintainers
Security News
pnpm's new minimumReleaseAge setting delays package updates to prevent supply chain attacks, with other tools like Taze and NCU following suit.
Security News
The Rust Security Response WG is warning of phishing emails from rustfoundation.dev targeting crates.io users.