Skip to main content

npm

Source

See the Plugins guide for how plugins from wolfstar-project/plugins fit alongside the core framework.

Description

@wolfstar/plugin-scheduled-tasks runs tasks later or on a schedule, such as unmuting a member in an hour or sending a report every morning. It is the counterpart of @sapphire/plugin-scheduled-tasks for @wolfstar/http-framework. Tasks are pieces. BullMQ stores their jobs in Redis, so jobs survive a restart and every process of the bot shares them. The plugin requires @wolfstar/http-framework 6.1.0 or later and a Redis server.

Registering the plugin

With the stars CLI, list the package in modules and set its options under the scheduledTasks key. It needs the optional @wolfstar/kit peer dependency, at ^0.2.0 || ^0.3.0.
stars.config.ts
The module reads its options from the scheduledTasks key of stars.config. The [specifier, options] tuple of modules still works. Its options are merged over the scheduledTasks key, so they win. The optional @wolfstar/schema peer dependency types the scheduledTasks key in defineConfig. TypeScript only loads that type once the module is imported, so import @wolfstar/plugin-scheduled-tasks in stars.config.ts. The CLI writes options from stars.config into the built entry, so they must be JSON-serialisable. Without the CLI, or to pass an ioredis instance, give the plugin to the client:
ClientOptions.tasks is merged over the plugin’s options, so you can also set the connection there:
Use either modules or plugins, not both. Registering the plugin twice runs its hooks twice and starts two workers on the same queue. The @wolfstar/plugin-scheduled-tasks/register entrypoint exists for the CLI and does nothing. If no bull.connection is set in either place, the plugin throws a TypeError when the client initializes. In ClientOptions, tasks accepts bull, queue, ready, readyTimeout, and readyDelay, and loadScheduledTaskErrorListeners overrides loadErrorListeners.

Writing a task

A task is a piece of the scheduled-tasks store, placed in the scheduled-tasks directory:
src/scheduled-tasks/unmute.ts
The ScheduledTasks interface types the payload everywhere. Use never for a task without a payload, and a union with undefined for an optional one.

Scheduling a task

create returns the BullMQ job. The second argument is either a delay in milliseconds or an options object with delay, interval, or pattern and timezone, plus optional customJobOptions. container.tasks.client is the BullMQ Queue itself.

Repeated tasks

A task with an interval in milliseconds or a cron pattern is scheduled when the client starts listening:
src/scheduled-tasks/report.ts
timezone defaults to UTC. A repeated task is a BullMQ job scheduler named after the task. Changing the pattern or interval in your code replaces its schedule on the next start. Deleting the piece does not delete the scheduler from Redis. Remove it with container.tasks.deleteRepeated('report'), and list existing schedulers with container.tasks.listRepeated().

Waiting for the app to be ready

When the worker starts, it immediately takes any job that came due while the bot was down. That can happen before the app has what the task needs, such as the gateway cache. Use the ready option to tell the plugin when the app is ready, and set waitForReady: true on the tasks that depend on it. ready returns true, or a promise that resolves to anything but false, when the app is ready:
src/scheduled-tasks/poststats.ts
Before a waitForReady task runs, its job waits up to readyTimeout for ready. If ready returns false, the plugin calls it again every 250 ms until the timeout. If the app is still not ready, the plugin moves the job back to delayed for readyDelay and the client emits scheduledTaskNotReady. The delayed job costs no attempt and does not emit scheduledTaskError. If ready throws or rejects, the job fails like a task error.
  • Tasks without waitForReady never wait. waitForReady defaults to false.
  • waitForReady does nothing if you don’t set ready.
  • The worker runs one job at a time, so a waiting job holds back the other tasks for up to readyTimeout. Lower it if that matters.
To wait inside a task by hand, call container.tasks.waitForReady(). It resolves to true once the app is ready, or false if it still isn’t after the timeout. It defaults to readyTimeout, and resolves to true immediately without a ready option:
ready is a function, so you can’t set it in stars.config. Pass it to scheduledTasks() or ClientOptions.tasks instead. You can still set readyTimeout and readyDelay in stars.config.

Events

The client emits these events, whose names are in ScheduledTaskEvents:
  • scheduledTaskRun, scheduledTaskSuccess, scheduledTaskError, scheduledTaskFinished, and scheduledTaskNotFound around every run.
  • scheduledTaskNotReady when a task that waits for the app is delayed because the app isn’t ready. The plugin installs no listener for it, so add one if you want to log it.
  • scheduledTaskStrategyConnectError, scheduledTaskStrategyClientError, and scheduledTaskStrategyWorkerError for Redis and BullMQ failures.
A task that throws fails its job. BullMQ retries the job according to its attempts, which you set with customJobOptions.

Shutting down

Differences from @sapphire/plugin-scheduled-tasks

  • It runs on BullMQ 6, where repeated tasks are job schedulers. listRepeated() returns JobSchedulerJson[], and deleteRepeated(name) is new.
  • The worker starts once the pieces are loaded rather than when the handler is constructed. A job is never taken before its task exists.
  • ClientOptions.tasks is optional, since you can give the options to the plugin instead.
version downloads license