Added lastRunAt to the scheduleEvent payload

This commit is contained in:
Eric Allam
2023-01-26 10:12:57 +00:00
parent 1374c10d99
commit e37a2001e1
11 changed files with 148 additions and 24 deletions
+5
View File
@@ -0,0 +1,5 @@
---
"@trigger.dev/sdk": patch
---
Added lastRunAt to the scheduleEvent payload
+14 -5
View File
@@ -39,7 +39,11 @@
"navigation": [ "navigation": [
{ {
"group": "Getting Started", "group": "Getting Started",
"pages": ["welcome", "getting-started", "get-help"] "pages": [
"welcome",
"getting-started",
"get-help"
]
}, },
{ {
"group": "Examples", "group": "Examples",
@@ -67,11 +71,15 @@
"pages": [ "pages": [
{ {
"group": "Slack", "group": "Slack",
"pages": ["integrations/apis/slack/actions/post-message"] "pages": [
"integrations/apis/slack/actions/post-message"
]
}, },
{ {
"group": "Resend.com", "group": "Resend.com",
"pages": ["integrations/apis/resend/actions/send-email"] "pages": [
"integrations/apis/resend/actions/send-email"
]
} }
] ]
}, },
@@ -102,7 +110,8 @@
"pages": [ "pages": [
"reference/trigger", "reference/trigger",
"reference/custom-event", "reference/custom-event",
"reference/webhook-event" "reference/webhook-event",
"reference/schedule-event"
] ]
}, },
{ {
@@ -128,4 +137,4 @@
"github": "https://github.com/triggerdotdev/trigger.dev", "github": "https://github.com/triggerdotdev/trigger.dev",
"discord": "https://discord.gg/nkqV9xBYWy" "discord": "https://discord.gg/nkqV9xBYWy"
} }
} }
+2
View File
@@ -7,6 +7,8 @@ description: "Trigger a workflow when a custom event is received."
## Usage ## Usage
```ts ```ts
import { customEvent, Trigger } from "@trigger.dev/sdk";
new Trigger({ new Trigger({
id: "user-created-notify-slack", id: "user-created-notify-slack",
name: "User Created - Notify Slack", name: "User Created - Notify Slack",
+68
View File
@@ -0,0 +1,68 @@
---
title: "scheduleEvent Trigger"
sidebarTitle: "scheduleEvent"
description: "Run a workflow on a recurring schedule."
---
## Usage
```ts
import { scheduleEvent } from "@trigger.dev/sdk";
new Trigger({
id: "usage",
name: "usage",
on: scheduleEvent({ rateof: { minutes: 10 } }),
run: async (event, ctx) => {},
}).listen();
```
## Options
You must use one of the following options, but not both:
<ParamField path="rateOf" type="object" required={false}>
The rate of the schedule. This can be a number of minutes, hours,
or days. For example, `{ rateOf: { minutes: 10 } }` will run
every 10 minutes.
</ParamField>
<ParamField path="cron" type="string" required={false}>
A cron expression to run the workflow on. For example, `0 0 * * *` will run
the workflow every hour at the top of the hour. See
[crontab.guru](https://crontab.guru/) for more information.
</ParamField>
## Event Payload
<ResponseField name="scheduledTime" type="Date" required={true}>
The time the event was scheduled to run.
</ResponseField>
<ResponseField name="lastRunAt" type="Date" required={false}>
The time the event last run. This will be `undefined` if the event has never run. Use this parameter to run window queries:
```ts
import { scheduleEvent, Trigger } from "@trigger.dev/sdk";
new Trigger({
id: "usage",
name: "usage",
on: scheduleEvent({ rateof: { minutes: 10 } }),
run: async (event, ctx) => {
const { lastRunAt, scheduledTime } = event;
const query = `SELECT * FROM users WHERE created_at < ${scheduledTime}`;
if (lastRunAt) {
query += ` AND created_at > ${lastRunAt}`;
}
const latestUsers = await db.query(query);
// ...
},
}).listen();
```
</ResponseField>
+2 -5
View File
@@ -9,6 +9,8 @@ description: "The Trigger class let's you define a workflow that is triggered by
### Usage ### Usage
```ts ```ts
import { customEvent, Trigger } from "@trigger.dev/sdk";
const trigger = new Trigger({ const trigger = new Trigger({
id: "user-created-notify-slack", id: "user-created-notify-slack",
name: "User Created - Notify Slack", name: "User Created - Notify Slack",
@@ -39,11 +41,6 @@ const trigger = new Trigger({
`TRIGGER_API_KEY` environment variable. `TRIGGER_API_KEY` environment variable.
</ParamField> </ParamField>
<ParamField path="apiKey" type="string" required={false}>
Your Trigger.dev API key. If not provided, the API key will be read from the
`TRIGGER_API_KEY` environment variable.
</ParamField>
<ParamField path="endpoint" type="string" required={false}> <ParamField path="endpoint" type="string" required={false}>
The URL of the Trigger.dev WebSocket server. If not provided, the endpoint The URL of the Trigger.dev WebSocket server. If not provided, the endpoint
will point to the production server. will point to the production server.
+2
View File
@@ -7,6 +7,8 @@ description: "Trigger a workflow when a webhook event is received"
## Usage ## Usage
```ts ```ts
import { webhookEvent, Trigger } from "@trigger.dev/sdk";
new Trigger({ new Trigger({
id: "caldotcom-to-slack", id: "caldotcom-to-slack",
name: "Cal.com To Slack", name: "Cal.com To Slack",
+32
View File
@@ -4,6 +4,8 @@ sidebarTitle: "Scheduled"
description: "Run a workflow on a recurring schedule" description: "Run a workflow on a recurring schedule"
--- ---
See the [reference](/reference/schedule-event) for more details.
## Examples ## Examples
### Every 5 minutes ### Every 5 minutes
@@ -51,3 +53,33 @@ new Trigger({
}, },
}).listen(); }).listen();
``` ```
## Preventing late runs
To prevent a scheduled trigger from running late, you can set a `triggerTTL` option when creating the `Trigger`, like so:
```ts
new Trigger({
id: "scheduled-workflow",
name: "Scheduled Workflow",
apiKey: "<your_api_key>",
on: scheduleEvent({ rateOf: { minutes: 5 } }),
triggerTTL: 300,
run: async (event, ctx) => {
await ctx.logger.info("Received the scheduled event", {
event,
wallTime: new Date(),
});
return { foo: "bar" };
},
}).listen();
```
This will prevent the trigger from running if it is running more than `300` seconds behind, which can happen if the server running your `Trigger` code goes down or is otherwise unavailable.
This is especially useful for scheduled triggers that run on a very short interval, like every minute, so you don't get a backlog of runs that all run at once when the server comes back online.
<Tip>
Set your `triggerTTL` to the same time (or double) as the rateOf the trigger.
</Tip>
@@ -29,7 +29,13 @@ export class ScheduleNextEvent {
const messageId = await taskQueue.publish( const messageId = await taskQueue.publish(
"DELIVER_SCHEDULED_EVENT", "DELIVER_SCHEDULED_EVENT",
{ externalSourceId: schedulerSource.id, payload: { scheduledTime } }, {
externalSourceId: schedulerSource.id,
payload: {
scheduledTime,
lastRunAt: fromEvent ? fromEvent.createdAt : undefined,
},
},
{}, {},
{ deliverAt: scheduledTime.getTime() } { deliverAt: scheduledTime.getTime() }
); );
@@ -5,19 +5,20 @@ import { prisma } from "~/db.server";
export const uptimeCheck = new Trigger({ export const uptimeCheck = new Trigger({
id: "uptime-check", id: "uptime-check",
name: "Uptime Check", name: "Uptime Check",
on: scheduleEvent({ rateOf: { minutes: 1 } }), on: scheduleEvent({ rateOf: { minutes: 5 } }),
triggerTTL: 300, logLevel: "info",
triggerTTL: 60,
run: async (event, context) => { run: async (event, context) => {
if (context.environment === "development" && !context.isTest) {
return;
}
// Grab counts of workflows, runs, and steps // Grab counts of workflows, runs, and steps
const userCount = await prisma.user.count(); const userCount = await prisma.user.count();
const workflowCount = await prisma.workflow.count(); const workflowCount = await prisma.workflow.count();
const runCount = await prisma.workflowRun.count(); const runCount = await prisma.workflowRun.count();
const stepCount = await prisma.workflowRunStep.count(); const stepCount = await prisma.workflowRunStep.count();
if (context.environment === "development") {
return;
}
await slack.postMessage("Uptime Notification", { await slack.postMessage("Uptime Notification", {
channelName: "monitoring", channelName: "monitoring",
text: `[${context.environment}] Uptime Check: ${userCount} users, ${workflowCount} workflows, ${runCount} runs, ${stepCount} steps.`, text: `[${context.environment}] Uptime Check: ${userCount} users, ${workflowCount} workflows, ${runCount} runs, ${stepCount} steps.`,
+8 -7
View File
@@ -2,20 +2,21 @@ import { Trigger, scheduleEvent } from "@trigger.dev/sdk";
import { slack } from "@trigger.dev/integrations"; import { slack } from "@trigger.dev/integrations";
const trigger = new Trigger({ const trigger = new Trigger({
id: "schedule-to-slack", id: "schedule-to-slack-2",
name: "Send to Slack every minute", name: "Send to Slack every minute",
apiKey: "trigger_development_vzNnO2DGBGcG", apiKey: "trigger_dev_zC25mKNn6c0q",
endpoint: "ws://localhost:8889/ws",
logLevel: "debug", logLevel: "debug",
on: scheduleEvent({ rateOf: { minutes: 1 } }), on: scheduleEvent({ rateOf: { minutes: 1 } }),
run: async (event, ctx) => { run: async (event, ctx) => {
await ctx.logger.info("It's me, the annoying slack bot!"); await ctx.logger.info("It's me, the annoying slack bot!");
const response = await slack.postMessage("slaaaaaack", { // const response = await slack.postMessage("slaaaaaack", {
channel: "test-integrations", // channelName: "test-integrations",
text: `Hello, the time is ${event.scheduledTime}`, // text: `Hello, the time is ${event.scheduledTime}, and I was last run at ${event.lastRunAt}!`,
}); // });
return response.message; return event;
}, },
}); });
+1
View File
@@ -29,6 +29,7 @@ export const EventFilterSchema: z.ZodType<EventFilter> = z.lazy(() =>
); );
export const ScheduledEventPayloadSchema = z.object({ export const ScheduledEventPayloadSchema = z.object({
lastRunAt: z.coerce.date().optional(),
scheduledTime: z.coerce.date(), scheduledTime: z.coerce.date(),
}); });