temporal-time-utils
TypeScript icon, indicating that this package has built-in type declarations

0.0.5 • Public • Published

temporal-time-utils

This is a library with some reusable functions for Temporal.io TypeScript SDK:

  • sleepUntil: sleep to a specific date, instead of by num of milliseconds
  • UpdatableTimer: sleep to a specific date, updatable and queryable
  • ScheduleWorkflow: schedule other workflows by extended cron syntax, with support for jitter, timezone, max invocations, manual triggers, pausing/unpausing, querying future executions, and more.

This serves as both a utility library and a demonstration of how you can publish reusable Temporal libraries (both for Workflows and Activities).

npm i temporal-time-utils

Repo: https://github.com/sw-yx/temporal-time-utils

sleepUntil

This is a simple drop in replacement for Temporal's workflow.sleep() API for when you need to sleep to a specific date rather than a fixed number of milliseconds.

import { sleepUntil } from "temporal-time-utils";

// inside workflow function
sleepUntil("30 Sep " + (new Date().getFullYear() + 1)); // wake up when September ends
sleepUntil("5 Nov 2022 00:12:34 GMT"); // wake up at specific time and timezone

// optional 2nd arg
sleepUntil("5 Nov 2022 00:12:34 GMT", specificDateTime); // take control over the "start" time in case you need to

This is a very simple function - under the hood it just uses date-fns/differenceInMilliseconds to calculate time difference.

This is discussed in the docs https://docs.temporal.io/docs/typescript/workflows#sleep

UpdatableTimer

sleep only lets you set a fixed time upfront. UpdatableTimer is a special class that lets you update that while sleeping. You can consider it the next step up from sleepUntil.

After you instantiate it with an initial datetime to wake up at, it exposes only two APIs: then() for you to await, and .deadline that you can set and get.

// example usage inside workflow function
export async function countdownWorkflow(initialDeadline: Date): Promise<void> {
  const timer = new UpdatableTimer(initialDeadline);
  wf.setHandler(
    setDeadlineSignal,
    (deadline) => void (timer.deadline = deadline)
  ); // send in new deadlines via Signal
  wf.setHandler(timeLeftQuery, () => timer.deadline - Date.now()); // get time left via Query
  await timer; // if you send in a signal with a new time, this timer will resolve earlier!
  console.log("countdown done!");
}

This is discussed in the docs https://docs.temporal.io/docs/typescript/workflows#async-design-patterns.

ScheduleWorkflow

A Workflow that schedules other Workflows.

This is a premade Workflow that you can register in a Worker and call from a client, to invoke other Workflows on a schedule. You can consider this the next step up from "Cron Workflows".

See example usage inside of /apps/fixture:

// inside client file
async function run() {
  const client = new WorkflowClient();
  const handle = await client.start(ScheduleWorkflow, {
    args: [
      "exampleWorkflow", // workflow to be executed on a schedule. must be string name.
      {
        args: ["Example arg payload"], // static for now, but possible to modify to make dynamic in future - ask swyx
        // // regular workflow options apply here, with two additions (defaults shown):
        // cancellationType: ChildWorkflowCancellationType.WAIT_CANCELLATION_COMPLETED,
        // parentClosePolicy: ParentClosePolicy.PARENT_CLOSE_POLICY_TERMINATE
      },
      {
        // args
        cronParser: {
          expression: "* * * * *", // every minute
          // options: https://www.npmjs.com/package/cron-parser#user-content-options
        },
        // maxInvocations?: number;
        // jitterMs?: number;
      },
    ],
    taskQueue: "tutorial",
    workflowId: "my-schedule-id",
  });
}

This uses https://www.npmjs.com/package/cron-parser under the hood, thereby getting support for things like timezones and "last of the week" extensions to the cron syntax:

// client.ts
const handle = await client.start(ScheduleWorkflow, {
  args: [
    "exampleWorkflow", // as above
    {}, // if no args needed
    {
      // scheduleOptions
      cronParser: {
        expression: "0 0 * * * 1,3L", // run every Monday as well as the last Wednesday of the month
        options: {
          currentDate: "2016-03-27 00:00:01",
          endDate: new Date("Wed, 26 Dec 2012 14:40:00 UTC"),
          tz: "Europe/Athens",
        },
      },
      maxInvocations: 500,
      jitterMs: 1000,
    },
  ],
  taskQueue: "scheduler",
  workflowId: "schedule-for-" + userId,
});

The Workflow exposes a number of useful queries and signals:

import {
  numInvocationsQuery,
  futureScheduleQuery,
  manualTriggerSignal,
  ScheduleWorkflowState,
  stateSignal,
  stateQuery,
  // ...
} from "temporal-time-utils";

await handle.query(numInvocationsQuery); // get how many times exampleWorkflow has been invoked by ScheduleWorkflow
await handle.query(futureScheduleQuery, 3); // get the next 3 times it is set to be invoked. defaults to 5
await handle.signal(manualTriggerSignal); // manually trigger workflow
await handle.signal(stateSignal, "PAUSED" as ScheduleWorkflowState); // pause workflow
await handle.signal(stateSignal, "RUNNING" as ScheduleWorkflowState); // resume workflow
await handle.cancel(); // stop schedule workflow completely
await handle.query(stateQuery); // get wf state (running, paused, or stopped)

Package Sidebar

Install

npm i temporal-time-utils

Weekly Downloads

48

Version

0.0.5

License

MIT

Unpacked Size

13.7 kB

Total Files

9

Last publish

Collaborators

  • sw-yx