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.
BlazerJob currently supports only the following connectors for actual execution:
| Connector Type | Status | Description |
|---|---|---|
cosmos |
Supported | Send tokens, query balances/transactions, batch Cosmos queries |
http |
Supported | Generic HTTP requests (GET, POST, etc.) |
shell |
Not supported | Present in types, but not executed (ignored/logged only) |
onchain |
Not supported | Present in types, but not executed (ignored/logged only) |
solana |
Not supported | Present in types, but not executed (ignored/logged only) |
email |
Not supported | Present in types, but not executed (ignored/logged only) |
fintech |
Not supported | Present in types, but not executed (ignored/logged only) |
Only tasks of type
cosmosandhttpare actually executed by BlazerJob. All other types are reserved for future extensions or compatibility, but are currently ignored or simply logged by the server.
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.
const jobs = new BlazeJob({ dbPath: './tasks.db', 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();BlazerJob natively supports HTTP tasks for scheduling API calls (GET, POST, etc.).
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' }
})
});jobs.schedule(async () => {}, {
runAt: new Date(),
type: 'http',
config: JSON.stringify({
url: 'https://api.coindesk.com/v1/bpi/currentprice.json',
method: 'GET'
})
});BlazerJob supports Cosmos blockchain tasks for sending tokens, querying balances, and more.
- Accepted type:
cosmos - Features:
- Token transfer (sendTokens)
- Balance queries, transactions (tx), and custom queries
- Batch Cosmos queries via
scheduleManyCosmosQueries
jobs.schedule(async () => {}, {
runAt: new Date(),
type: 'cosmos',
config: JSON.stringify({
queryType: 'balance',
queryParams: { address: 'cosmos1...' }
})
});jobs.schedule(async () => {}, {
runAt: new Date(),
type: 'cosmos',
config: JSON.stringify({
to: 'cosmos1...',
amount: '100000',
denom: 'uatom',
mnemonic: process.env.COSMOS_MNEMONIC,
chainId: 'cosmoshub-4',
rpcUrl: process.env.COSMOS_RPC_URL
})
});COSMOS_MNEMONIC– Cosmos mnemonicCOSMOS_RPC_URL– Cosmos RPC endpoint
Any type other than cosmos (e.g., shell, onchain, solana, email, fintech, http) will be ignored and simply logged. To extend, you will need to reactivate or develop the corresponding connector.
BlazerJob provides a CLI to easily manage your scheduled tasks:
# Show help
npx ts-node src/bin/cli.ts help
# Schedule a task (e.g., shell)
npx ts-node src/bin/cli.ts schedule --type shell --cmd "echo hello" --runAt "2025-01-01T00:00:00Z"
# List tasks (default blazerjob.db)
npx ts-node src/bin/cli.ts list
# List tasks from ALL .db files in the current directory
ts-node src/bin/cli.ts list-all
# Delete a task
npx ts-node src/bin/cli.ts delete 123Displays tasks from all .db files in the current directory, with separate sections for each database.
Example Output:
=== Database: blazerjob.db ===
┌─────────┬────┬─────────┬────────────────────────────┬──────────┬─────────────────────────────┐
│ (index) │ id │ type │ runAt │ status │ config │
├─────────┼────┼─────────┼────────────────────────────┼──────────┼─────────────────────────────┤
│ 0 │ 1 │ 'cosmos' │ '2025-05-05T21:24:13.727Z' │ 'failed' │ '{"cmd":"echo test"}' │
└─────────┴────┴─────────┴────────────────────────────┴──────────┴─────────────────────────────┘
=== Database: tasks_cosmos_query.db ===
┌─────────┬────┬──────────┬────────────────────────────┬──────────┬─────────────────────────────────────┐
│ (index) │ id │ type │ runAt │ status │ config │
├─────────┼────┼──────────┼────────────────────────────┼──────────┼─────────────────────────────────────┤
│ 0 │ 42 │ 'cosmos' │ '2025-05-06T02:21:28.275Z' │ 'failed' │ '{"queryType":"balance",...}' │
└─────────┴────┴──────────┴────────────────────────────┴──────────┴─────────────────────────────────────┘
Shows tasks only from the default database (blazerjob.db).
Schedules a new task. Available options:
--type: Task type (cosmos)--cmd: Command to execute (for cosmos tasks)--runAt: Execution time (default: now)--interval: Repeat interval in ms (optional)--priority: Task priority (optional)--retriesLeft: Number of retry attempts (optional)--webhookUrl: Webhook URL for notifications (optional)
Deletes a task by its ID.
npm install blazerjob- SQLite WAL enabled by default (
journal_mode = WAL) to avoid reader/writer blocking. - 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 { BlazeJob } from 'blazerjob';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:
COSMOS_MNEMONIC=0xYOUR_COSMOS_MNEMONIC
COSMOS_RPC_URL=https://mainnet.infura.io/v3/YOUR_INFURA_KEY
- 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.
- dbPath: Path to the SQLite database file where tasks are stored.
- 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.'cosmos').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.
Returns the ID of the created task.
- Starts the scheduler loop (automatically executes due tasks).
- Stops the scheduler loop (does not close the database).
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({ dbPath: './test.db', 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.');
});- Enable
autoExitonly for scripts or tests. - In production/server, leave
autoExitasfalse(the default) to prevent unexpected process termination.
BlazerJob supports the following task types and config structures:
type TaskType = 'cosmos';
interface CosmosTaskConfig {
queryType: 'balance' | 'tx' | 'custom';
queryParams?: Record<string, string>;
to?: string;
amount?: string;
denom?: string;
mnemonic?: string;
chainId?: string;
rpcUrl?: string;
}If you set webhookUrl when scheduling a task, BlazerJob will POST a JSON payload to that URL on task completion (success, failure, or retry).
{
"taskId": 42,
"status": "done",
"executedAt": "2025-05-05T23:50:00Z",
"result": "success",
"output": null,
"error": null
}{
"taskId": 42,
"status": "failed",
"executedAt": "2025-05-05T23:51:00Z",
"result": "error",
"output": null,
"error": "Command failed: ..."
}{
"taskId": 42,
"status": "pending",
"executedAt": "2025-05-05T23:52:00Z",
"result": "retry",
"output": null,
"error": "Temporary error message"
}Here’s how to use BlazerJob to execute a simple query on Cosmos (for example, to get the balance of an address or transaction info):
import { BlazeJob } from 'blazerjob';
const jobs = new BlazeJob({ dbPath: './tasks.db' });
jobs.schedule(async () => {}, {
runAt: new Date(),
type: 'cosmos',
config: JSON.stringify({
queryType: 'balance',
queryParams: { address: 'cosmos1...' },
// rpcUrl peut venir de .env ou être spécifié ici
})
});
jobs.start();import { BlazeJob } from 'blazerjob';
const jobs = new BlazeJob({ dbPath: './tasks.db' });
jobs.schedule(async () => {}, {
runAt: new Date(),
type: 'cosmos',
config: JSON.stringify({
queryType: 'tx',
queryParams: { hash: '0x...' },
// rpcUrl peut venir de .env ou être spécifié ici
})
});
jobs.start();- Results are logged on the server side (console).
- For a custom query, use
queryType: 'custom'and adaptqueryParamsas needed.
BlazerJob now lets you schedule an HTTP API request (using fetch):
import { BlazeJob } from 'blazerjob';
const jobs = new BlazeJob({ dbPath: './tasks.db' });
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' }
})
});
jobs.start();jobs.schedule(async () => {}, {
runAt: new Date(),
type: 'http',
config: JSON.stringify({
url: 'https://api.coindesk.com/v1/bpi/currentprice.json',
method: 'GET'
})
});import { BlazeJob } from 'blazerjob';
const jobs = new BlazeJob({ dbPath: './tasks.db' });
jobs.schedule(async () => {}, {
runAt: new Date(),
interval: 10000, // toutes les 10 secondes
type: 'http',
config: JSON.stringify({
url: 'https://api.coindesk.com/v1/bpi/currentprice.json',
method: 'GET'
})
});
jobs.start();Pour logguer la réponse côté serveur, modifie la fonction dans le code source :
taskFn = async () => { const res = await fetch(cfg.url, { method: cfg.method ?? 'POST', headers: cfg.headers, body: cfg.body ? JSON.stringify(cfg.body) : undefined }); const text = await res.text(); console.log('[HTTP][response]', text); };
BlazerJob centralizes all Cosmos blockchain logic in the src/cosmos/ module. This module exposes helpers for scheduling, querying, and sending tokens on Cosmos chains (CosmJS-compatible).
- Batch scheduling: Schedule hundreds of Cosmos queries or transactions in one call.
- Unified helpers: Query balances, transactions, and send tokens using a simple API.
- Environment support: Cosmos mnemonic and RPC URL can be set in
.envor provided per task. - Error handling: Centralized error helpers for Cosmos-specific issues (rate limits, etc).
- TypeScript-first: All helpers are typed for safe use.
import { BlazeJob } from 'blazerjob';
import { scheduleManyCosmosQueries } from './src/cosmos';
const job = new BlazeJob({ dbPath: './tasks.db' });
await scheduleManyCosmosQueries(job, {
addresses: [
'cosmos1fl48vsnmsdzcv85q5d2q4z5ajdha8yu34mf0eh',
'cosmos1c9ye9j3p4e9w8f7j2k7l6k8e8f7g9h5d3j8k7h',
],
count: 100,
queryType: 'balance',
intervalMs: 100,
});
job.start();import { getBalance, getTx } from './src/cosmos';
const balances = await getBalance(process.env.COSMOS_RPC_URL, 'cosmos1...');
const tx = await getTx(process.env.COSMOS_RPC_URL, '0x...');import { sendTokens } from './src/cosmos';
await sendTokens({
rpcUrl: process.env.COSMOS_RPC_URL,
mnemonic: process.env.COSMOS_MNEMONIC,
to: 'cosmos1destination...',
amount: '100000',
denom: 'uatom',
chainId: 'cosmoshub-4',
});COSMOS_MNEMONIC– Cosmos wallet mnemonicCOSMOS_RPC_URL– Cosmos RPC endpoint
See .env.example for details.
BlazerJob exposes various Cosmos helpers in src/cosmos/queries.ts:
getBalance(rpcUrl, address): Gets the balance of an addressgetTx(rpcUrl, hash): Retrieves a transaction by hashsendTokens({rpcUrl, mnemonic, to, amount, denom, ...}): Sends ATOM or other tokensgetLatestBlockHeight(rpcUrl): Gets the latest block heightgetBlockByHeight(rpcUrl, height): Gets block details by heightgetAccountInfo(rpcUrl, address): Gets account info (account number, sequence, ...)getAllBalances(rpcUrl, address): Gets all balances for an addressgetChainId(rpcUrl): Gets the chain IDgetTransactionByHash(rpcUrl, hash): Alias forgetTxsearchTxs(rpcUrl, query): Searches transactions (by address, event, ...)broadcastTx(rpcUrl, txBytes): Broadcasts a signed transactiongetDelegation(rpcUrl, delegator, validator): Gets specific staking delegation
Some advanced queries (validators, supply, node info) require a REST/LCD endpoint (not included in StargateClient, see cosmjs/launchpad/lcd or fetch).
import {
getBalance, getTx, sendTokens, getLatestBlockHeight, getBlockByHeight,
getAccountInfo, getAllBalances, getChainId, getTransactionByHash, searchTxs,
broadcastTx, getDelegation
} from './src/cosmos';
const balances = await getAllBalances(process.env.COSMOS_RPC_URL, 'cosmos1...');
const block = await getBlockByHeight(process.env.COSMOS_RPC_URL, 1234567);
const delegation = await getDelegation(process.env.COSMOS_RPC_URL, 'cosmos1delegator...', 'cosmosvaloper1validator...');GNU