Gathering detailed insights and metrics for @ramplex/clujo
Gathering detailed insights and metrics for @ramplex/clujo
Gathering detailed insights and metrics for @ramplex/clujo
Gathering detailed insights and metrics for @ramplex/clujo
Schedule functions on a cron-like schedule. Built in distributed locking to prevent overlapping executions in a clustered environment.
npm install @ramplex/clujo
Typescript
Module System
Node Version
NPM Version
TypeScript (100%)
Total Downloads
0
Last Day
0
Last Week
0
Last Month
0
Last Year
0
MIT License
4 Stars
171 Commits
1 Watchers
1 Branches
1 Contributors
Updated on Jun 14, 2025
Latest Version
5.0.0
Package Id
@ramplex/clujo@5.0.0
Unpacked Size
211.74 kB
Size
21.83 kB
File Count
27
NPM Version
10.9.2
Node Version
22.16.0
Published on
Jun 11, 2025
Cumulative downloads
Total Downloads
Last Day
0%
NaN
Compared to previous day
Last Week
0%
NaN
Compared to previous week
Last Month
0%
NaN
Compared to previous month
Last Year
0%
NaN
Compared to previous year
2
IMPORTANT: clujo is now published under @ramplex/clujo
on npm and jsr. If you are using the old clujo
package, please update your dependencies to use @ramplex/clujo
instead. All future versions will be published under the new package name.
Clujo is a simple and flexible solution for running any object with a trigger
method on a cron schedule, with built-in support for preventing overlapping executions in distributed environments.
It would not be possible without the amazing work of the following projects:
ioredis
instance is provided) - used to ensure single execution in a distributed environmentComing soon: validated bun support.
trigger
function and a cron scheduleClujo is available on jsr and npm, and supports Node.js and Deno v2.0.0 or later.
Install Clujo using npm, pnpm, yarn:
1npm install @ramplex/clujo 2yarn add @ramplex/clujo 3pnpm install @ramplex/clujo
1deno add jsr:@ramplex/clujo
1npx jsr add @ramplex/clujo 2yarn dlx jsr add @ramplex/clujo 3pnpm dlx jsr add @ramplex/clujo
Here's a simple example to get you started with Clujo:
1import { Clujo } from '@ramplex/clujo'; 2// or (in node.js) 3// const { Clujo } = require('@ramplex/clujo'); 4 5// Create any object with a trigger function 6const myRunner = { 7 trigger: async () => { 8 console.log("Running my scheduled task!"); 9 // Do your work here 10 const result = await performSomeWork(); 11 return result; 12 } 13}; 14 15// Create a Clujo instance 16const clujo = new Clujo({ 17 id: "my-scheduled-job", 18 cron: { 19 pattern: "*/5 * * * *", // Every 5 minutes 20 options: { tz: "America/New_York" } 21 }, 22 runner: myRunner, 23 // Optional: prevent overlapping executions in distributed environments 24 redis: { client: redisClient }, 25 // Optional: run immediately on startup 26 runOnStartup: true, 27}); 28 29// Start the job 30clujo.start(); 31 32// Manually trigger if needed 33const result = await clujo.trigger(); 34 35// Gracefully stop 36await clujo.stop();
Clujo works with any object that implements a simple interface:
1interface IRunner<T> { 2 trigger: () => T | Promise<T>; 3}
This means you can schedule anything - from simple functions wrapped in an object to complex workflow systems, database maintenance tasks, or API polling jobs.
By default, Clujo prevents overlapping executions on a single instance. If a job is still running when the next scheduled execution arrives, the new execution is skipped. This behavior is automatic and requires no configuration.
For distributed environments with multiple instances, you can provide a Redis client to ensure only one instance executes the job at any given time across your entire system.
You can specify multiple cron patterns for a single job:
1const clujo = new Clujo({ 2 id: "multi-schedule-job", 3 cron: { 4 patterns: [ 5 "0 9 * * *", // Daily at 9 AM 6 "0 17 * * *", // Daily at 5 PM 7 "0 12 * * SAT" // Saturdays at noon 8 ] 9 }, 10 runner: myRunner 11});
Schedule a job to run once at a specific date/time:
1const clujo = new Clujo({ 2 id: "holiday-job", 3 cron: { 4 pattern: new Date("2024-12-25T00:00:00") // Christmas midnight 5 }, 6 runner: myRunner 7});
To disable a Clujo from executing on its schedule, use the enabled
option:
1const clujo = new Clujo({ 2 id: "conditional-job", 3 cron: { 4 pattern: "*/5 * * * *" 5 }, 6 runner: myRunner, 7 enabled: process.env.NODE_ENV === "production" 8});
When disabled, the Clujo will still exist but will skip execution when triggered.
Clujo supports custom logging through a logger interface. The logger can be provided to the Clujo instance to capture various events and errors during execution. Each log level is optional, and you can choose to implement only the methods you need.
1// Define a logger that implements the IClujoLogger interface 2interface IClujoLogger { 3 debug?: (message: string) => void; 4 log?: (message: string) => void; 5 error?: (message: string) => void; 6} 7 8// Example implementation using console 9const consoleLogger = { 10 log: (message) => console.log(`[Clujo] ${message}`), 11 debug: (message) => console.debug(`[Clujo] ${message}`), 12 error: (message) => console.error(`[Clujo] ${message}`) 13}; 14 15// Or a custom logger 16const customLogger = { 17 log: (message) => myLoggingService.info(message), 18 debug: (message) => myLoggingService.debug(message), 19 error: (message) => myLoggingService.error(message) 20}; 21 22// Provide the logger to Clujo 23const clujo = new Clujo({ 24 id: "myClujoJob", 25 runner: myRunner, 26 cron: { pattern: "*/5 * * * *" }, 27 logger: customLogger 28});
The logger will capture various events such as:
If no logger is provided, Clujo will operate silently without logging any events.
When running multiple instances of your application, use Redis to ensure only one instance executes a job at a time:
1import Redis from 'ioredis'; 2 3const client = new Redis(); 4 5const clujo = new Clujo({ 6 id: "distributed-job", 7 cron: { pattern: "*/5 * * * *" }, 8 runner: myRunner, 9 redis: { 10 client, 11 lockOptions: { 12 lockTimeout: 30000, // Lock expires after 30 seconds 13 acquireTimeout: 10000 // Wait up to 10 seconds to acquire lock 14 } 15 }, 16});
Execute the job immediately when starting, in addition to the scheduled times:
1const clujo = new Clujo({ 2 id: "startup-job", 3 cron: { pattern: "0 * * * *" }, // Every hour 4 runner: myRunner, 5 runOnStartup: true // Also runs immediately when started 6});
You can manually trigger a job outside of its schedule:
1// This runs independently of the schedule and any running instances 2const result = await clujo.trigger(); 3console.log("Manual execution result:", result);
The Scheduler class provides a convenient way to manage multiple Clujo jobs together. It allows you to add, start, and stop groups of jobs in a centralized manner.
It is not required and Clujo
's can be managed manually if desired.
1import { Scheduler } from '@ramplex/clujo'; 2import { Redis } from 'ioredis'; 3 4const scheduler = new Scheduler(); 5 6// Add jobs to the scheduler 7scheduler.addJob(myFirstClujo); 8scheduler.addJob(mySecondClujo); 9 10// Add more jobs as needed
You can start all added jobs at once, optionally providing a Redis instance for distributed locking:
1// Start all jobs 2scheduler.start();
To stop all running jobs:
1// Stop all jobs with a default timeout of 5000ms 2await scheduler.stop(); 3 4// Or, specify a custom timeout in milliseconds 5await scheduler.stop(10000);
1let count = 0; 2 3const counter = { 4 trigger: async () => { 5 count++; 6 console.log(`Count is now: ${count}`); 7 return count; 8 } 9}; 10 11const clujo = new Clujo({ 12 id: "counter", 13 cron: { pattern: "*/10 * * * * *" }, // Every 10 seconds 14 runner: counter 15}); 16 17clujo.start();
1const dbCleanup = { 2 trigger: async () => { 3 const db = await getDatabase(); 4 const deleted = await db.deleteOldRecords(30); // 30 days old 5 console.log(`Cleaned up ${deleted} old records`); 6 return { deletedCount: deleted, timestamp: new Date() }; 7 } 8}; 9 10const clujo = new Clujo({ 11 id: "db-cleanup", 12 cron: { pattern: "0 2 * * *" }, // Daily at 2 AM 13 runner: dbCleanup, 14 redis: { client: redisClient }, // Prevent multiple instances from running 15 logger: { 16 log: (msg) => logger.info(msg), 17 error: (msg) => logger.error(msg), 18 debug: (msg) => logger.debug(msg) 19 } 20});
Clujo works seamlessly with @ramplex/workflow
for complex task orchestration:
1import { Clujo } from '@ramplex/clujo'; 2import { Workflow } from '@ramplex/workflow'; 3 4const workflow = new Workflow() 5 .addNode({ 6 id: "fetch", 7 execute: async () => { 8 const data = await fetchData(); 9 return data; 10 } 11 }) 12 .addNode({ 13 id: "process", 14 dependencies: ["fetch"], 15 execute: async (ctx) => { 16 const processed = await processData(ctx.fetch); 17 return processed; 18 } 19 }) 20 .addNode({ 21 id: "save", 22 dependencies: ["process"], 23 execute: async (ctx) => { 24 await saveResults(ctx.process); 25 return { saved: true }; 26 } 27 }) 28 .build(); 29 30const clujo = new Clujo({ 31 id: "data-pipeline", 32 cron: { pattern: "0 */6 * * *" }, // Every 6 hours 33 runner: workflow, 34 redis: { client: redisClient } 35}); 36 37clujo.start();
Contributions are welcome! Please describe the contribution in an issue before submitting a pull request. Attach the issue number to the pull request description and include tests for new features / bug fixes.
@ramplex/clujo is MIT licensed.
No vulnerabilities found.
No security vulnerabilities found.