Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/lorensr/temporal-time-utils
This is a library with some reusable functions for Temporal.io TypeScript SDK
https://github.com/lorensr/temporal-time-utils
job-scheduler nodejs temporalio timers
Last synced: 12 days ago
JSON representation
This is a library with some reusable functions for Temporal.io TypeScript SDK
- Host: GitHub
- URL: https://github.com/lorensr/temporal-time-utils
- Owner: lorensr
- Created: 2022-01-03T19:29:50.000Z (almost 3 years ago)
- Default Branch: main
- Last Pushed: 2022-09-09T17:17:47.000Z (about 2 years ago)
- Last Synced: 2024-10-11T08:09:04.122Z (29 days ago)
- Topics: job-scheduler, nodejs, temporalio, timers
- Language: TypeScript
- Homepage: https://www.npmjs.com/package/temporal-time-utils
- Size: 91.8 KB
- Stars: 18
- Watchers: 1
- Forks: 0
- Open Issues: 3
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
- awesome-temporal - `lorensr/temporal-time-utils` - `sleepUntil` and `UpdatableTimer`. (TypeScript / Libraries)
README
# temporal-time-utils
This is a library with some reusable functions for [Temporal.io TypeScript SDK](https://docs.temporal.io/docs/typescript/introduction):
- `sleepUntil`: sleep to a specific date, instead of by number of milliseconds
- `UpdatableTimer`: sleep to a specific date, updatable and queryable
- `ScheduleWorkflow`: *[Deprecated in favor of [Schedules](https://docs.temporal.io/workflows#schedule)]* 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).
⚠️ **Note:** This is not an officially supported Temporal library due to the fact that `sleepUntil` and `UpdatableTimer` are not guaranteed to be accurate: the number of milliseconds until the given date is calculated up front, so if any time/date adjustments are made (like changes in timezones, daylight savings, leap seconds), the timer may not fire at the exact correct time.
```ts
npm i 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.
```ts
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.
```ts
// example usage inside workflow function
export async function countdownWorkflow(initialDeadline: Date): Promise {
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/lorensr/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/lorensr/temporal-time-utils/blob/main/apps/fixture/src/workflows.ts#L5 necessary export for Worker to pick it up```ts
// 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:
```ts
// 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:
```ts
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)
```This is a decoupled and slightly modified variant of what was discussed in the docs: https://docs.temporal.io/docs/typescript/workflows#schedule-workflow-example
## Monorepo details
This project is bootstrapped with https://turborepo.org/.
### Build
To build all apps and packages, run the following command:
```
cd my-turborepo
npm run build
```### Develop
To develop all apps and packages, run the following command:
```
cd my-turborepo
npm run dev
```### Remote Caching
Turborepo can use a technique known as [Remote Caching (Beta)](https://turborepo.org/docs/features/remote-caching) to share cache artifacts across machines, enabling you to share build caches with your team and CI/CD pipelines.
```
cd my-turborepo
npx turbo login
npx turbo link
```