blazerjob
v2.0.7
Published
TypeScript library for scheduling, executing, and managing asynchronous tasks (custom, HTTP) with a SQLite backend.
Maintainers
Readme
BlazerJob – Task Scheduler Library
BlazerJob is a lightweight, SQLite-backed task scheduler for Node.js and TypeScript applications. Use it as a library in your code to schedule, execute, and manage asynchronous tasks.
Quick start
import { BlazeJob } from "blazerjob";
const jobs = new BlazeJob({
storage: "sqlite",
dbPath: "./blazerjob.db",
concurrency: 4
});
jobs.schedule(async () => {
console.log("Job executed");
}, { runAt: new Date() });
await jobs.start();Task Types
BlazerJob supports two types of tasks:
| Task Type | Description |
|-----------|------------------------------------------------|
| custom | Arbitrary JavaScript/TypeScript functions (most flexible) |
| http | Generic HTTP requests (GET, POST, etc.) |
1. Custom Tasks (Arbitrary JavaScript/TypeScript)
BlazerJob can schedule and execute any custom asynchronous JavaScript/TypeScript function. This is the most flexible way to use the scheduler, and is ideal for business logic, scripts, or workflows that don't fit a predefined connector.
Example: Custom Task
const jobs = new BlazeJob({ concurrency: 16 });
jobs.schedule(async () => {
// Your custom logic here
console.log('Hello from a custom task!');
// You can use any Node.js/TypeScript code
}, {
runAt: new Date(),
interval: 5000, // optional: repeat every 5 seconds
maxRuns: 3, // optional: stop after 3 executions
onEnd: (stats) => {
console.log('Task finished. Stats:', stats);
}
});
jobs.start();Storage Options
BlazerJob supports two storage modes:
Memory Storage (Default)
BlazerJob uses in-memory storage by default for maximum performance. Tasks are stored in RAM using SQLite's :memory: mode and are lost when the process restarts.
const jobs = new BlazeJob({
concurrency: 16
});Use case: Ideal for testing, temporary tasks, or when persistence is not required.
SQLite File Storage (Persistent)
For persistent task storage across process restarts, use SQLite file storage:
const jobs = new BlazeJob({
storage: 'sqlite',
dbPath: './tasks.db',
concurrency: 16
});Use case: Production environments where task persistence is required.
Note: Custom JavaScript/TypeScript task functions are always stored in memory (via
Map), regardless of storage mode. Only task metadata and configurations are persisted to SQLite.
2. HTTP Tasks (API Calls)
BlazerJob natively supports HTTP tasks for scheduling API calls (GET, POST, etc.).
Example: HTTP POST Request
jobs.schedule(async () => {}, {
runAt: new Date(),
type: 'http',
config: JSON.stringify({
url: 'https://httpbin.org/post',
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: { hello: 'world' }
})
});Example: HTTP GET Request
jobs.schedule(async () => {}, {
runAt: new Date(),
type: 'http',
config: JSON.stringify({
url: 'https://api.coindesk.com/v1/bpi/currentprice.json',
method: 'GET'
})
});HTTP Server
BlazerJob includes a built-in HTTP server (Fastify) for managing tasks via REST API.
Starting the Server
import { startServer } from 'blazerjob';
await startServer(9000); // Server runs on http://localhost:9000API Endpoints
- GET /tasks: List all scheduled tasks
- POST /task: Schedule a new task (JSON body with runAt, type, config, etc.)
- DELETE /task/:id: Delete a task by ID
Important: The HTTP server uses in-memory storage by default. Tasks will be lost when the server restarts. For persistence, modify the server initialization to use
storage: 'sqlite'.
Example: Schedule via HTTP
curl -X POST http://localhost:9000/task \
-H "Content-Type: application/json" \
-d '{
"runAt": "2026-01-01T00:00:00Z",
"type": "http",
"config": {
"url": "https://api.example.com",
"method": "GET"
}
}'Installation
npm install blazerjobNote: Installation may take a bit longer because BlazerJob builds native SQLite bindings (
better-sqlite3). If you're on a fresh machine, ensure build tools are available (e.g., Python + a C/C++ compiler) before installing.
Performance & tuning
- SQLite WAL enabled by default for file storage (
journal_mode = WAL) to avoid reader/writer blocking (not applied to in-memory storage). - Concurrency configured via
concurrencyoption (default1for backward compatibility). - Scheduler interval lowered to 50 ms + immediate drain when all slots are used.
Synthetic benchmarks (fake tasks, local NVMe) :
| Concurrency | Task duration | Observed throughput | |-------------|---------------|---------------------| | 16 | 50 ms | ~31 tasks/s (with logs) | | 32 | 50 ms | ~544 tasks/s | | 64 | 50 ms | ~982 tasks/s | | 64 | 10 ms | ~1,156 tasks/s | | 128 | 10 ms | ~2,183 tasks/s | | 256 | 10 ms | ~3,096 tasks/s | | 512 | 10 ms | ~4,367 tasks/s | | 1024 | 10 ms | ~4,464 tasks/s |
Numbers depend heavily on CPU/I/O; tune concurrency to match your workload.
Import
import { BlazeJob } from 'blazerjob';Environment Variables & Secrets
BlazerJob uses dotenv to securely load secrets (like private keys and RPC URLs) from a .env file.
- Copy
.env.exampleto.envand fill in your secrets:
cp .env.example .envExample .env:
# Add your custom environment variables here as needed- Never commit your real
.envto version control! - You can omit
privateKeyandrpcUrlfrom the task config to use values from the environment. - This pattern can be used for other secrets (API keys, fintech credentials, etc.) in custom handlers.
API Reference
new BlazeJob(options: BlazeJobOptions)
- storage?: Storage mode -
'memory'(default, in-memory) or'sqlite'(persistent file storage) - dbPath?: Path to the SQLite database file (only used when
storage: 'sqlite', defaults to'blazerjob.db') - concurrency?: Number of concurrent tasks to execute (default:
1) - autoExit?: Automatically exit process when all periodic tasks complete (default:
false) - encryptionKey?: Custom encryption key for task configs (default: uses
BLAZERJOB_ENCRYPTION_KEYenv var or a default key) - debug?: Enables internal scheduler logs (like
tick) when set totrue(default:false)
schedule(taskFn: () => Promise, opts: { ... }): number
- taskFn: Asynchronous function to execute (your JS/TS code).
- opts:
runAt: Date or ISO string for when to run the task.interval?: (optional) Number of milliseconds between executions (for recurring tasks).priority?: (optional) Higher priority tasks run first.retriesLeft?: (optional) Number of retry attempts if the task fails.type: Task type (e.g.'http').config?: (optional) Additional configuration for the task, see TaskConfig below.webhookUrl?: (optional) If set, BlazerJob will POST a JSON payload to this URL on task success, failure, or retry.maxRuns?: (optional) Maximum number of executions for periodic tasks.maxDurationMs?: (optional) Maximum duration in milliseconds for periodic tasks.onEnd?: (optional) Callback function called when task completes with stats{ runCount, errorCount }.
Returns the ID of the created task.
start(): Promise
- Starts the scheduler loop (automatically executes due tasks).
stop(): void
- Stops the scheduler loop (does not close the database).
deleteTask(taskId: number): void
- Deletes a task by ID and cleans up associated memory (task functions, stats, error counts).
getTasks(): any[]
- Returns all tasks from the database with decrypted configurations.
Automatic Process Exit (autoExit option)
For testing or scripting purposes, you can configure BlazeJob to automatically exit the process as soon as all periodic tasks (with maxRuns or maxDurationMs) are completed:
const jobs = new BlazeJob({ autoExit: true });
jobs.schedule(async () => {}, {
runAt: new Date(),
interval: 2000,
maxRuns: 3,
onEnd: (stats) => {
console.log('Summary:', stats);
}
});
jobs.start();
// The process will automatically exit after the last periodic task is finished.- If
autoExitis not enabled, the process will continue running as usual. - You can also use the global
onAllTasksEndedcallback to perform actions at the end, without stopping the process:
jobs.onAllTasksEnded(() => {
console.log('All periodic tasks are done.');
});Best Practices
- Enable
autoExitonly for scripts or tests. - In production/server, leave
autoExitasfalse(the default) to prevent unexpected process termination.
TaskConfig Interface
BlazerJob supports the following task type and config structure:
type TaskType = 'http';
interface HttpTaskConfig {
url: string;
method?: string;
headers?: Record<string, string>;
body?: any;
}Webhook Notifications
If you set webhookUrl when scheduling a task, BlazerJob will POST a JSON payload to that URL on task completion (success, failure, or retry).
Example Payload (Success)
{
"taskId": 42,
"status": "done",
"executedAt": "2025-05-05T23:50:00Z",
"result": "success",
"output": null,
"error": null
}Example Payload (Failure)
{
"taskId": 42,
"status": "failed",
"executedAt": "2025-05-05T23:51:00Z",
"result": "error",
"output": null,
"error": "Command failed: ..."
}Example Payload (Retry)
{
"taskId": 42,
"status": "pending",
"executedAt": "2025-05-05T23:52:00Z",
"result": "retry",
"output": null,
"error": "Temporary error message"
}License
GNU
