Replies: 8 comments 2 replies
-
Other considerations that will need some more in-depth exploration:
|
Beta Was this translation helpful? Give feedback.
-
The code below that you suggested wouldn't work, should actually work. Assuming that we add an extra step to deal with secrets automatically. // tasks.background.ts
import { client } from "./trigger";
import { db } from "./db";
export const task1 = client.defineBackgroundTask({
id: "task-1",
name: "Task 1",
version: "1.0.0",
schema: z.object({
userId: z.string(),
}),
run: async (payload) => {
// This wouldn't work
await db.users.findById(payload.id);
},
}); When this code is bundled (using tsup or similar) it will automatically bundle the This leaves the challenge of secrets. Rather than explicitly having to define them, I think it would be better if we automatically find them all. This can be achieved (for TS/JS) by searching the bundled code for Locally we can automatically set the env var values by using the values from the .env file. For deployment, we’d have the list of env vars which we’d display in the UI so values can be set – we'd have to allow them to be unset so we can support optionals. |
Beta Was this translation helpful? Give feedback.
-
Some more thoughts/questions:
|
Beta Was this translation helpful? Give feedback.
-
Background
|
Beta Was this translation helpful? Give feedback.
-
Background Function Library proposalBefore we expose the ability for end-users to develop their own custom Background Functions, we're going to implement a common library of internal background functions that can be used by users without any additional work. We currently have ad-hoc support for Background Fetch which does a The Background Function Library will move this ad-hoc "Background Fetch" into just 1 of many different background functions that can be referenced and called within Job runs and within integrations. In addition to Background Fetch, we could offer the following functions:
The Background Function Library would be implemented in a way that would prepare for opening up the ability for users to define their own background functions (see my previous comment for more on that). This would allow us to work out bugs and the experience of background functions before we open it up to end users. It would also give us the ability to satisfy more users who want to perform certain long-running tasks quicker. Considerations for self-hostersThis will add an additional docker image to run for self-hosters called We considered not creating another docker image for this, and instead adding the runtime for the Background Function library into the main trigger.dev docker image, but didn't think there would be much benefit to this as it would overload the image and it's tricky to run multi-process docker images and could lead to issues. But this is still something we haven't 100% decided on. DXCurrently, using background fetch looks like this: import { eventTrigger } from "@trigger.dev/sdk";
import { client } from "@/trigger";
client.defineJob({
id: "function-usage-1",
name: "Background Function Usage",
version: "0.0.1",
trigger: eventTrigger({
name: "example.event",
}),
run: async (payload, io, ctx) => {
const output = await io.backgroundFetch("fetch-1", "https://example.api", {
method: "POST",
body: JSON.stringify(payload),
});
return { output };
},
}); In the new version background fetch would be imported and invoked from the import { eventTrigger } from "@trigger.dev/sdk";
import { client } from "@/trigger";
import { fetchFunction } from "@trigger.dev/functions";
client.defineJob({
id: "function-usage-1",
name: "Background Function Usage",
version: "0.0.1",
trigger: eventTrigger({
name: "example.event",
}),
run: async (payload, io, ctx) => {
const output = await fetchFunction.invoke("fetch-1", "https://example.api", {
method: "POST",
body: JSON.stringify(payload),
});
return { output };
},
}); Code StructureThe following packages/apps would be added to the monorepo:
|
Beta Was this translation helpful? Give feedback.
-
This feature is what pipedream special. Anyone know any similar product in zapier's space had this feature? Their Node, Python, Bash & Go runtimes, is extremely feasible and amazing. |
Beta Was this translation helpful? Give feedback.
-
I'm going to close this discussion as it's superseded by what we're going to be calling v3. |
Beta Was this translation helpful? Give feedback.
-
Exciting proposal! Have you considered leveraging Crawlbase for web scraping tasks within your Background Functions? It could seamlessly integrate with your existing setup, offering reliable and scalable web scraping capabilities. Plus, it aligns with your aspiration of an easy-to-use solution while enhancing task diversity. Just a thought! |
Beta Was this translation helpful? Give feedback.
-
Currently, Trigger.dev does not host user code and run it, instead it coordinates through an API endpoint hosted on user's machine or deployment. This setup works well for some use-cases, especially ones that mix 3rd party services with local services/databases (think of the proverbial email drip campaign that checks a user's status in the db between emails). But this setup suffers from issues when a single task might take longer than a function execution timeout, as it will never finish and we will never be able to complete the job. Here are some common function timeouts on various serverless platforms:
We've gotten feedback from quite a few people who have individual tasks that take longer than some of these function timeouts would allow, so they've wanted the ability to reliably run longer tasks.
Because this is not possible with our current approach, we are proposing introducing the idea of Background Tasks that would run on external infrastructure and be orchestrated by Trigger.dev.
Use cases
Developer Experience
The aspirational DX for this feature should be "as easy as deploying to Vercel", all while writing code in the same repo/codebase as your existing project. It should be fully integrated into Trigger.dev and the Trigger.dev dashboard, allowing task observability and management. It should also ideally work with integrations.
To create a background task, you would create a file named with the pattern
<anything here>.background.ts
. Inside this file you would export 1 or more tasks:And you are able to use and invoke tasks inside of your existing Trigger.dev jobs:
The data needed inside the background task is defined in the
schema
and provided when invoking the background task (all with end-to-end typesafety.)Limitations and workarounds
Because background tasks would run separately from the user's local or deployed app, they wouldn't be able to access anything outside of the scope of the
run
function. For example, this wouldn't be possible:I propose we add the ability to configure background tasks with secrets to allow for this sort of use-case:
Development
During development, background tasks would be bundled and run locally when running the
@trigger.dev/cli dev
command. And invoking background tasks during development would call these locally running tasks.Deployment && Self-hostability
This is a tricky one, involving running untrusted code in a way that scales and doesn't cause "noisy neighbor" problems. All while being self-hostable while not requiring very complicated (or expensive) production setups. Here are some considered options:
Firecracker
Firecracker is a secure and fast microVMs for serverless computing, powering AWS Lambda and developed by AWS. This would allow highly scalable and fast mutlitenant user code running. Unfortunately, it's extremely expensive to host as it requires bare metal machines (e.g. $2k a month on AWS). It's also very complicated to configure and run securely.
WebAssembly
I wasn't able to find any Web Assembly runtimes that ran Node.js code without any hacks, but possibly more research into this is needed. There are just a ton of Web Assembly runtimes and none of them seemed to do what we need.
AWS Lamdba
Why not just ship user code to a lambda function and call it a day? For one, lambdas can run for a maximum of 15 minutes. Vercel Enterprise users can already get 15 minute function execution. And it would introduce a closed source element to the Trigger.dev project, for not that much benefit.
Fly.io <- what we're currently thinking
There are a lot of positives for choosing Fly.io. They have some very nice Machine APIs for this exact use case, that would allow us to bundle, deploy, and run background task code all through the Fly.io APIs. We would use Fly.io to independently scale and run machines for specific background tasks, based on their usage. We'd get code-isolation for free. It would also allow us to ship this feature (relatively) quickly, to guage interest and work out bugs and usability issues.
The downsides of course are that Fly.io is not open source, and isn't itself self-hostable. But if you were self-hosting Trigger.dev, you could make use of background tasks powered by Fly.io by setting a few environment variables (
FLY_API_TOKEN
andFLY_API_ORGANIZATION_ID
), so it'd be more likely for self-hosters to be able to support Background Tasks. We even already have some developers using Fly.io to self-host Trigger.dev.Architecture
TBD
Feedback
Please let us know if you have any thoughts on the above feature idea, we'd love to hear from you 👋.
Beta Was this translation helpful? Give feedback.
All reactions