Skip to content
This page View Markdown Open in ChatGPT Open in Claude

Schedulers

A scheduler is a TypeScript function which runs on a schedule : every few seconds, every night at two, on the first of the month, or on any cron expression, in the time zone you pick. On a cluster of servers each run happens once, on one server, and moves to another one when a server goes down.

Schedulers on a cluster : every interval runs once, on one server, spread over the servers, with failover schedulers of the account nightly-report 0 0 2 * * * · Asia/Kolkata sync-stock every 5 minutes · UTC send-reminders Mon-Fri 11:30 · Europe/Paris Redis knows which server runs each scheduler API Maker servers server 1 runs nightly-report server 2 runs sync-stock server 3 down · send-reminders moves Rules • each tick runs once, never on every server • spread over the servers • a server which goes down hands its jobs over • a deploy never breaks a run in progress • start, stop, run now from the admin panel

Create a scheduler

API Info → Schedulers, then +.

Field Meaning
Name Unique in the account, can not change later (it names the folder in Git). Label can.
Timeout in minutes The run is stopped after this long.
Code The function, with the global object g.
Intervals One or more, each with a time interval, a time zone and an active switch.
Active The master switch of the scheduler.
Run on native process Run in API Maker itself instead of the sandbox.
Save response in log Keep what the run returned in the log table.

The code

import * as T from 'types';
import * as db from 'db-interfaces';

async function main(g: T.IAMGlobal) {
    const stale = await g.sys.db.query({
        instance: 'mongodb', database: 'shop', collection: 'carts',
        find: { updated_at: { $lt: new Date(Date.now() - 7 * 86400000).toISOString() } },
        select: '_id',
    });
    const removed = await g.sys.db.removeByQuery({
        instance: 'mongodb', database: 'shop', collection: 'carts',
        find: { _id: { $in: stale.map(c => c._id) } },
    });
    g.logger.log(`${removed.deletedRowsCount} carts removed`);
    return { removed: removed.deletedRowsCount };
}
module.exports = main;
  • The same g as a custom API, without a request : g.req.body and g.req.query are empty. Use g.shared and the cache to keep state between runs.

Intervals

Group Choices
Seconds every second, 5, 10, 15, 30 seconds
Minutes every minute, 2, 3, 4, 5, 6, 10, 12, 15, 20, 30 minutes
Hours every hour, 2, 3, 4, 6, 8, 12 hours
Days every day, 2, 3, 5, 10, 15 days
Working days Monday to Friday at 11:30
Months every month, 2, 3, 4, 6 months
Year every year
Custom a cron expression
  • Each interval has its time zone : Asia/Kolkata, Europe/Paris, UTC… A scheduler with two intervals runs both.
  • Each interval has its own active switch, so one can be paused without touching the other.

Custom cron expressions

Six fields, seconds first : second minute hour day-of-month month day-of-week. Five fields work too (the seconds default to 0).

Expression Runs
0 0 22 * * 1-5 at 22:00, Monday to Friday
0 15 14 1 * * at 14:15 on the first of every month
*/30 * * * * * every 30 seconds
0 0 */6 * * * every 6 hours

On a cluster

  • Once per tick. Whatever the number of API Maker servers, an interval runs once : the servers agree through Redis which one runs each scheduler, and a scheduler already running is not started again.
  • Spread out. The schedulers of an account are spread over the servers instead of all running on one.
  • Failover. When a server stops, the schedulers it ran are picked up by the others.
  • Safe deployments. A Git pull or a deployment does not interrupt a run in progress ; the next run uses the new code.

Start, stop, run now

  • The Active switch starts and stops a scheduler right away, on every server : stop a misbehaving job in production in one click.
  • Run now from the API testing page (pick the scheduler, send) runs it once, outside its schedule, and shows the result and the logs.
  • The Schedulers page marks a scheduler running now on a node, and one whose intervals are all switched off : it never runs. Clone copies a scheduler.
  • Versions : keep several versions of the code, one active.

Good to know

  • A log profile records every run with its duration and its output.
  • Schedulers are files in Git (src/Schedulers/<name>/) and deploy with a pull. Their active state and intervals travel with them.
  • A scheduler which needs more than its timeout should split the work : page through the rows and keep a cursor in the cache.
  • Groups grant schedulers to API users for the testing page and the run API.