npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

temporal-time-utils

v0.0.5

Published

This is a library with some reusable functions for [Temporal.io TypeScript SDK](https://docs.temporal.io/docs/typescript/introduction):

Downloads

991

Readme

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:

  • https://github.com/sw-yx/temporal-time-utils/blob/main/apps/fixture/src/client.ts invoke the ScheduleWorkflow and pass in an example Workflow to call on a schedule
  • https://github.com/sw-yx/temporal-time-utils/blob/main/apps/fixture/src/workflows.ts#L5 necessary export for Worker to pick it up
// 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)