Changelog #53

·

Scheduled tasks for v3

Matt Aitken

Matt Aitken

CEO, Trigger.dev

Image for Scheduled tasks for v3

Now you can create scheduled tasks in Trigger.dev v3. If you haven't already you should sign up for the v3 waitlist.

At the end I'll reveal what schedule the cron pattern in the image above, 0 17 * * 5, represents. You cron nerds need closure.

In the video my scheduled task posts a GIF to Slack every minute.

Features

  • Define your task in code using schedules.task()
  • Attach many schedules (across environments) to each task in the dashboard.
  • Attach schedules using the SDK (you can do dynamic things like a schedule for each of your users using externalId)
  • List, view, edit, disable, re-enable, create and delete using the dashboard, SDK and REST API.
  • Use AI to help you create cron patterns in the dashboard.

Full docs here: https://trigger.dev/docs/tasks-scheduled

An example scheduled task

This is the scheduled task code from the video above.

/trigger/random-time-gif.ts

import { WebClient } from "@slack/web-api";
import { retry, schedules } from "@trigger.dev/sdk/v3";
const slack = new WebClient(process.env.SLACK_BOT_TOKEN);
//define the task using schedules.task()
export const randomTimeGif = schedules.task({
id: "random-time-gif",
run: async (payload) => {
//Get 25 GIFs related to "time" from the giphy API
const randomGifResponse = await retry.fetch(
`https://api.giphy.com/v1/gifs/search?api_key=${process.env.GIPHY_API_KEY}&q=time&limit=25&offset=0&rating=g&lang=en&bundle=messaging_non_clips`
);
const json = await randomGifResponse.json();
//pick a random GIF URL from the results
const resultCount = json.data.length;
const randomIndex = Math.floor(Math.random() * resultCount);
const url = json.data[randomIndex]?.url;
if (!url) {
throw new Error("No gif found");
}
//post to a Slack channel
const result = await slack.chat.postMessage({
text: url,
channel: process.env.SLACK_CHANNEL_ID!,
});
return { success: true };
},
});

As shown in the video, you can attach a schedule to this task in the dashboard. This is great for most use cases.

Dynamic schedules (or multi-tenant)

Using the SDK you can do more advanced scheduling. For example, you could let your users define a schedule that they want to post GIFs to their own Slack workspace channel.

First take what we had before and modify the task slightly:

/trigger/scheduled-slack-gif.ts

import { WebClient } from "@slack/web-api";
import { retry, schedules } from "@trigger.dev/sdk/v3";
import { db } from "@/db";
//define the task using schedules.task()
export const scheduledSlackGifs = schedules.task({
id: "scheduled-slack-gifs",
run: async (payload) => {
//we'll set the externalId to a row in our database when we create the schedule
if (!payload.externalId) {
throw new Error("externalId is required");
}
//get the details of what the user wants
const { slackToken, slackChannelId, gifSearchQuery } =
await db.getGifSchedule(payload.externalId);
//Get 25 GIFs related to "time" from the giphy API
const randomGifResponse = await retry.fetch(
`https://api.giphy.com/v1/gifs/search?api_key=${
process.env.GIPHY_API_KEY
}&q=${encodeURIComponent(
gifSearchQuery
)}=25&offset=0&rating=g&lang=en&bundle=messaging_non_clips`
);
const json = await randomGifResponse.json();
//pick a random GIF URL from the results
const resultCount = json.data.length;
const randomIndex = Math.floor(Math.random() * resultCount);
const url = json.data[randomIndex]?.url;
if (!url) {
throw new Error("No gif found");
}
//post to a Slack channel
const slack = new WebClient(slackToken);
const result = await slack.chat.postMessage({
text: url,
channel: slackChannelId,
});
return { success: true };
},
});

Then in your backend code you need to register a schedule for this task. This is a Next.js server action but the only thing that matters is that it's on your server:


"use server";
import { scheduledSlackGifs } from "@/trigger/scheduled-user-gifs";
import { schedules } from "@trigger.dev/sdk/v3";
import { db } from "@/db";
export async function registerSchedule(
userId: string,
cron: string,
searchQuery: string
) {
try {
//create a record for the GIF schedule for this user
const row = await db.createGifSchedule(userId, searchQuery);
//create a new schedule for this GIF schedule
const createdSchedule = await schedules.create({
task: scheduledSlackGifs.id,
cron,
//the row id, so we can retrieve the row inside the run
externalId: row.id,
//don't allow multiple shedules for the same GIF schedule
deduplicationKey: row.id,
});
return { scheduleId: createdSchedule.id };
} catch (error) {
console.error(error);
return {
error: "something went wrong",
};
}
}

The user has defined their own reminder frequency and what kind of GIFs they want.

Read the full docs for everything that scheduled tasks allow.

So the cron pattern 0 17 * * 5 is every Friday at 5pm (UTC). I hope that helps you sleep at night.

Ready to start building?

Build and deploy your first task in 3 minutes.

Get started now