Pipsqueak is an in memory interval based task scheduler, with support for promises, callbacks and synchronous functions. Pipsqueak is also the name of a Hamster. Hamsters like running in circles. A bit like an interval based task scheduler, but more cute.
Pipsqueak allows you to:
- Monitor a task's lifecycle through
begin
,end
anderror
events - Reduce the boilerplate code associated with setTimeout/setInterval
- Randomly stagger execution when running multiple instances
- Configure intervals in human readable form
- Prevent overlapping tasks
- Stop worrying about unref
const { promiseApi: pipsqueak } = require('pipsqueak');
const factory = (ctx) => new Promise((resolve, reject) => {
resolve(new Date().toISOString());
})
const p = pipsqueak({ name: 'example', factory: factory, interval: '1s', delay: '1s' })
.on('begin', ({ name, run, }) => console.log(`begin: ${name}/${run}`))
.on('end', ({ name, run, result }) => console.log(`end: ${name}/${run} ${result}`))
.on('error', ({ name, run, error }) => console.error(`error: ${name}/${run} ${error.message}`))
.start();
n.b. In order for the promise to be re-evaluated a factory must be used
const { callbackApi: pipsqueak } = require('pipsqueak');
const task = (ctx, cb) => cb(null, new Date().toISOString());
const p = pipsqueak({ name: 'example', task: task, interval: '1s', delay: '1s' })
.on('begin', ({ name, run, }) => console.log(`begin: ${name}/${run}`))
.on('end', ({ name, run, result }) => console.log(`end: ${name}/${run} ${result[0]}`))
.on('error', ({ name, run, error }) => console.error(`error: ${name}/${run} ${error.message}`))
.start();
n.b. the results are an array
const { synchronousApi: pipsqueak } = require('pipsqueak');
const task = (ctx) => new Date().toISOString();
const p = pipsqueak({ name: 'example', task: task, interval: '1s', delay: '1s' })
.on('begin', ({ name, run, }) => console.log(`begin: ${name}/${run}`))
.on('end', ({ name, run, result }) => console.log(`end: ${name}/${run} ${result}`))
.on('error', ({ name, run, error }) => console.error(`error: ${name}/${run} ${error.message}`))
.start();
begin: example/39195fc7-7035-48a2-9f73-ef6476ff3fdd
end: example/39195fc7-7035-48a2-9f73-ef6476ff3fdd 2018-02-10T22:41:51.025Z
begin: example/2c3fc5c6-c5dd-4233-8979-21b047b443b6
end: example/2c3fc5c6-c5dd-4233-8979-21b047b443b6 2018-02-10T22:41:56.028Z
begin: example/aa6b7d7f-608b-4469-b874-18fda2457a45
end: example/aa6b7d7f-608b-4469-b874-18fda2457a45 2018-02-10T22:42:01.029Z
You can specify multiple tasks by passing pipsqueak an array instead of a map
const { promiseApi: pipsqueak } = require('pipsqueak');
const factory = (ctx) => new Promise((resolve, reject) => {
resolve(new Date().toISOString());
})
const tasks = [
{ name: 'example-1', factory: factory, interval: '1s', delay: '1s' },
{ name: 'example-2', factory: factory, interval: '5s' },
]
const p = pipsqueak(tasks)
.on('begin', ({ name, run, }) => console.log(`begin: ${name}/${run}`))
.on('end', ({ name, run, result }) => console.log(`end: ${name}/${run} ${result}`))
.on('error', ({ name, run, error }) => console.error(`error: ${name}/${run} ${error.message}`))
.start();
You must set an interval, but an initial delay is optional. Values may be integers, parsable strings or if you want a random duration, an object containing max
and optional min
properties.
const { promiseApi: pipsqueak } = require('pipsqueak');
const factory = (ctx) => new Promise((resolve, reject) => {
resolve(new Date().toISOString());
})
const interval = { min: '1m', max: '5m' };
const delay = { max: '1m' };
const p = pipsqueak({ name: 'example', factory, interval, delay }).start();
Calling stop will cancel any schedule runs and prevent new runs from being scheduled. You can specify a shutdown timeout at a task level
const tasks = [
{ name: 'example-1', factory: factory, interval: '1s', timeout: '2s' },
{ name: 'example-2', factory: factory, interval: '5s', timeout: '5s' },
]
const { promiseApi: pipsqueak } = require('pipsqueak');
const p = pipsqueak(tasks).start()
p.stop().then(() => {
...
}).catch(err => {
console.error(err.message);
});
const { callbackApi: pipsqueak } = require('pipsqueak');
const p = pipsqueak(tasks).start();
p.stop(function(err) {
if (err) console.error(err.message);
...
})
Synchronous tasks are blocking, so there's no need to wait for them
You can force a task or tasks to run by poking them.
const p = pipsqueak(tasks).start();
p.poke();
p.poke('task1');
p.poke(['task1', 'task2']);
If pipsqueak is stopped, or the task was running or disabled, poking it will have no effect. If pipsqueak was not started, the task will be run once, but not scheduled. If pipsqueak was started, the next schedule will be cancelled, the task will be run once and rescheduled.
If you want to configure, but disable a specific tasks (maybe because it should only run under specific conditions, set disabled
to true, e.g.
pipsqueak({ name: 'example', task: task, interval: '1s', disabled: true })
Emitted whenever the task begins.
Property | Type | Description |
---|---|---|
name | String | The supplied task runner name. |
run | UUID | Uniquely identifies the run. |
iteration | Integer | The number of times the task has been executed |
timestamp | Integer | The current time in millis |
Emitted whenever the task finishes.
Property | Type | Description |
---|---|---|
name | String | The supplied task runner name. |
run | UUID | Uniquely identifies the run. |
iteration | Integer | The number of times the task has been executed |
timestamp | Integer | The current time in millis |
result | Mixed | The result of the task, passed the the callback, resolved or returned |
Emitted whenever the task errors.
Property | Type | Description |
---|---|---|
name | String | The supplied task runner name. |
run | UUID | Uniquely identifies the run. |
iteration | Integer | The number of times the task has been executed |
timestamp | Integer | Uniquely identifies the run. |
error | Error | The error object thrown, rejected or passed to the callback |
To run with debug enabled set DEBUG=pipsqueak