Skip to content

Add support for specifying machine preset at trigger time #1608

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Jan 15, 2025

Conversation

nicktrn
Copy link
Collaborator

@nicktrn nicktrn commented Jan 13, 2025

What it says on the tin.

// Same as usual, will use the machine preset on childTask, defaults to "small-1x"
await childTask.trigger({ message: "Hello, world!" });

// This will override the task's machine preset and any defaults. Works with all trigger functions.
await childTask.trigger({ message: "Hello, world!" }, { machine: "small-2x" });
await childTask.triggerAndWait({ message: "Hello, world!" }, { machine: "small-2x" });

await childTask.batchTrigger([
  { payload: { message: "Hello, world!" }, options: { machine: "micro" } },
  { payload: { message: "Hello, world!" }, options: { machine: "large-1x" } },
]);
await childTask.batchTriggerAndWait([
  { payload: { message: "Hello, world!" }, options: { machine: "micro" } },
  { payload: { message: "Hello, world!" }, options: { machine: "large-1x" } },
]);

await tasks.trigger<typeof childTask>(
  "child",
  { message: "Hello, world!" },
  { machine: "small-2x" }
);
await tasks.batchTrigger<typeof childTask>("child", [
  { payload: { message: "Hello, world!" }, options: { machine: "micro" } },
  { payload: { message: "Hello, world!" }, options: { machine: "large-1x" } },
]);

To keep the task options in line, they now also accept a string in addition to the old object:

export const childTask = task({
  id: "child",
  // This is new
  machine: "micro",
  // This still works
  machine: {
    preset: "micro",
  },
  run: async (payload: any, { ctx }) => {
    // ...
  },
});

Summary by CodeRabbit

Release Notes

  • New Features

    • Added support for specifying machine presets when triggering tasks.
    • Users can now override the default machine preset for individual tasks or batch triggers.
    • Introduced flexibility to choose between "micro", "small-1x", "small-2x", "medium-1x", "medium-2x", "large-1x", and "large-2x" machine presets.
  • Improvements

    • Enhanced task execution configuration options.
    • More granular control over task run environments.

The changes provide developers with greater control over task execution by allowing custom machine preset selection during task triggering.

Copy link

changeset-bot bot commented Jan 13, 2025

🦋 Changeset detected

Latest commit: 952d011

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 12 packages
Name Type
@trigger.dev/sdk Patch
@trigger.dev/core Patch
@trigger.dev/build Patch
trigger.dev Patch
@internal/redis-worker Patch
@internal/zod-worker Patch
@trigger.dev/react-hooks Patch
@trigger.dev/rsc Patch
@trigger.dev/database Patch
@trigger.dev/otlp-importer Patch
references-nextjs-realtime Patch
@internal/testcontainers Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Copy link
Contributor

coderabbitai bot commented Jan 13, 2025

Warning

There were issues while running some tools. Please review the errors and either fix the tool’s configuration or disable the tool if it’s a critical failure.

🔧 eslint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

apps/webapp/app/v3/services/triggerTask.server.ts

Oops! Something went wrong! :(

ESLint: 8.45.0

ESLint couldn't find the config "custom" to extend from. Please check that the name of the config is correct.

The config "custom" was referenced from the config file in "/.eslintrc.js".

If you still have problems, please stop by https://eslint.org/chat/help to chat with the team.

Walkthrough

The pull request introduces support for specifying machine presets when triggering tasks in the Trigger SDK. This enhancement allows users to override the default machine preset for individual tasks or batch triggers. The changes span multiple files across the SDK and webapp, adding a new machinePreset option to various triggering functions and services. The implementation ensures that machine presets can be flexibly configured, with fallback mechanisms to default configurations when no specific preset is provided.

Changes

File Change Summary
packages/core/src/v3/schemas/api.ts Added optional machine field to TriggerTaskRequestBody and BatchTriggerTaskItem schemas.
packages/core/src/v3/types/tasks.ts Introduced MachinePresetName type and updated machine property in TaskOptions interface.
packages/trigger-sdk/src/v3/shared.ts Updated multiple trigger functions to include optional machine parameter.
apps/webapp/app/v3/machinePresets.server.ts Added new machinePresetFromRun function to validate and convert machine preset names.
apps/webapp/app/v3/services/* Updated services like CreateTaskRunAttemptService, RestoreCheckpointService, and TriggerTaskService to handle machine preset logic.

Sequence Diagram

sequenceDiagram
    participant User
    participant SDK
    participant WebApp
    participant TaskRunner

    User->>SDK: Trigger task with machinePreset
    SDK->>WebApp: Send task trigger request
    WebApp->>WebApp: Validate machinePreset
    alt Preset is valid
        WebApp->>TaskRunner: Assign specified machine preset
    else Preset is invalid
        WebApp->>TaskRunner: Use default machine preset
    end
    TaskRunner->>User: Execute task
Loading

Possibly related PRs

  • Add ability to update parent and root run metadata from children #1563: The changes in this PR enhance the ability to manage run metadata by allowing updates from child runs, which is directly related to the new functionality introduced in the main PR for specifying machine presets during task execution. Both PRs focus on improving the flexibility and control over task management and execution environments.

Poem

🐰 Hop, hop, machine preset's here to play,
Flexible tasks in a brand new way!
Small or large, the choice is clear,
Trigger SDK brings control so near!
Rabbits code with mighty might! 🚀


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 60e12cb and 952d011.

📒 Files selected for processing (6)
  • .changeset/gold-melons-fetch.md (1 hunks)
  • apps/webapp/app/v3/services/triggerTask.server.ts (1 hunks)
  • docs/v3-openapi.yaml (1 hunks)
  • packages/core/src/v3/schemas/api.ts (3 hunks)
  • packages/core/src/v3/types/tasks.ts (3 hunks)
  • packages/trigger-sdk/src/v3/shared.ts (11 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • apps/webapp/app/v3/services/triggerTask.server.ts
  • .changeset/gold-melons-fetch.md
  • packages/trigger-sdk/src/v3/shared.ts
👮 Files not reviewed due to content moderation or server errors (3)
  • packages/core/src/v3/schemas/api.ts
  • packages/core/src/v3/types/tasks.ts
  • docs/v3-openapi.yaml
⏰ Context from checks skipped due to timeout of 90000ms (7)
  • GitHub Check: typecheck / typecheck
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - pnpm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - npm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (buildjet-8vcpu-ubuntu-2204 - pnpm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (buildjet-8vcpu-ubuntu-2204 - npm)
  • GitHub Check: units / 🧪 Unit Tests
  • GitHub Check: Analyze (javascript-typescript)

Finishing Touches

  • 📝 Generate Docstrings (Beta)

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
apps/webapp/app/v3/machinePresets.server.ts (1)

34-42: Enhance error handling in machinePresetFromRun.

The function silently returns null when parsing fails. Consider logging the error for better debugging.

 export function machinePresetFromRun(run: { machinePreset: string | null }): MachinePreset | null {
-  const presetName = MachinePresetName.safeParse(run.machinePreset).data;
+  const parsed = MachinePresetName.safeParse(run.machinePreset);
+  if (!parsed.success) {
+    logger.debug("Failed to parse machine preset", { 
+      preset: run.machinePreset,
+      error: parsed.error 
+    });
+    return null;
+  }
 
-  if (!presetName) {
-    return null;
-  }
-
-  return machinePresetFromName(presetName);
+  return machinePresetFromName(parsed.data);
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 14ce599 and 60e12cb.

📒 Files selected for processing (9)
  • .changeset/gold-melons-fetch.md (1 hunks)
  • apps/webapp/app/v3/machinePresets.server.ts (1 hunks)
  • apps/webapp/app/v3/marqs/sharedQueueConsumer.server.ts (7 hunks)
  • apps/webapp/app/v3/services/createTaskRunAttempt.server.ts (2 hunks)
  • apps/webapp/app/v3/services/restoreCheckpoint.server.ts (3 hunks)
  • apps/webapp/app/v3/services/triggerTask.server.ts (1 hunks)
  • packages/core/src/v3/schemas/api.ts (3 hunks)
  • packages/core/src/v3/types/tasks.ts (2 hunks)
  • packages/trigger-sdk/src/v3/shared.ts (8 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (7)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - pnpm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - npm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (buildjet-8vcpu-ubuntu-2204 - pnpm)
  • GitHub Check: typecheck / typecheck
  • GitHub Check: e2e / 🧪 CLI v3 tests (buildjet-8vcpu-ubuntu-2204 - npm)
  • GitHub Check: units / 🧪 Unit Tests
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (9)
apps/webapp/app/v3/services/restoreCheckpoint.server.ts (1)

73-75: LGTM! Clean implementation of machine preset resolution.

The code correctly prioritizes the run-level machine preset while maintaining backward compatibility with config-based presets.

packages/core/src/v3/schemas/api.ts (2)

95-95: LGTM! Clean schema extension.

The machinePreset option is correctly added as an optional field with proper type safety.


136-136: LGTM! Consistent schema implementation.

The same machinePreset option is correctly added to batch triggers, maintaining consistency across the API.

packages/core/src/v3/types/tasks.ts (1)

779-783: LGTM! Well-documented type extension.

The machinePreset option is properly typed and documented, clearly explaining its purpose and behavior.

.changeset/gold-melons-fetch.md (1)

1-34: Well-documented feature with clear examples!

The changeset provides comprehensive documentation of the new machine preset feature, including:

  • Clear version bumps for affected packages
  • Detailed examples showing various usage patterns
  • Good coverage of all trigger function variants

The patch version bumps are appropriate as this is a backward-compatible feature addition.

packages/trigger-sdk/src/v3/shared.ts (1)

616-616: Clean and consistent implementation of machine preset support!

The implementation:

  • Adds machinePreset support consistently across all trigger functions
  • Maintains type safety through proper interface updates
  • Follows existing patterns for option handling

Also applies to: 790-790, 952-952, 1207-1207, 1267-1267, 1361-1361, 1438-1438

apps/webapp/app/v3/marqs/sharedQueueConsumer.server.ts (1)

416-418: Well-structured machine preset handling with proper fallbacks!

The implementation:

  • Consistently uses machinePresetFromRun with fallback to machinePresetFromConfig
  • Maintains backward compatibility through proper fallback mechanisms
  • Integrates smoothly with existing queue consumer logic

Also applies to: 547-549, 1083-1085, 1305-1307

apps/webapp/app/v3/services/createTaskRunAttempt.server.ts (2)

9-9: LGTM! Import changes align with the PR objective.

The addition of machinePresetFromRun import alongside machinePresetFromConfig supports the new feature for specifying machine presets at trigger time.


176-178: LGTM! Clear precedence in machine preset determination.

The implementation correctly prioritizes trigger-time machine preset specification with a proper fallback mechanism.

Let's verify the validation logic in the imported functions:

✅ Verification successful

Validation confirmed: Machine preset determination is robust and safe

The implementation includes proper validation with safe parsing, fallback mechanisms, and error logging:

  • Invalid configs fall back to "small-1x" preset
  • Invalid run presets return null, triggering the fallback to config-based preset
  • All user inputs are safely parsed before use
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check validation logic in machinePresets.server.ts

# Search for validation logic in machinePresetFromRun and machinePresetFromConfig
ast-grep --pattern 'function machinePresetFrom$_($_) {
  $$$
}'

# Look for any validation-related error handling
rg -A 5 "throw.*Error.*machine.*preset" "../machinePresets.server.ts"

Length of output: 203


Script:

#!/bin/bash
# First, find the machinePresets file
fd -t f machinePresets

# Once found, we'll examine its contents
# Look for both function definitions and any validation logic
ast-grep --pattern 'function machinePresetFrom$_($_) {
  $$$
}'

# Search for validation-related terms
rg -i "machine.*preset.*valid|invalid.*machine.*preset"

Length of output: 192


Script:

#!/bin/bash
# Examine the full content of the machine presets file
cat apps/webapp/app/v3/machinePresets.server.ts

Length of output: 1652

Copy link

pkg-pr-new bot commented Jan 13, 2025

@trigger.dev/react-hooks

npm i https://pkg.pr.new/triggerdotdev/trigger.dev/@trigger.dev/react-hooks@1608

@trigger.dev/rsc

npm i https://pkg.pr.new/triggerdotdev/trigger.dev/@trigger.dev/rsc@1608

trigger.dev

npm i https://pkg.pr.new/triggerdotdev/trigger.dev@1608

@trigger.dev/sdk

npm i https://pkg.pr.new/triggerdotdev/trigger.dev/@trigger.dev/sdk@1608

@trigger.dev/build

npm i https://pkg.pr.new/triggerdotdev/trigger.dev/@trigger.dev/build@1608

@trigger.dev/core

npm i https://pkg.pr.new/triggerdotdev/trigger.dev/@trigger.dev/core@1608

commit: 952d011

@ashleyww93
Copy link

Thank you for this! This will be great for us.

Is there a reason you went with machinePreset as a option instead of machine: { preset: '' }.

I know the other options in machine are deprecated, but it seems like it would be easier to maintain and document if the type was shared?

@nicktrn
Copy link
Collaborator Author

nicktrn commented Jan 14, 2025

Thank you for this! This will be great for us.

🙌

Is there a reason you went with machinePreset as a option instead of machine: { preset: '' }.

I know the other options in machine are deprecated, but it seems like it would be easier to maintain and document if the type was shared?

Yep, precisely due to the deprecation many months ago when we added v3 billing. Final name TBD and yet to add docs.

There will be some breaking changes to the SDK in the near future. Could be a good time to simplify new options even further, maybe in this case: machine: string

This could go hand in hand with an upcoming option to select the region or "worker group" (internal name for now - there could be multiple groups in the same region, with different features / prereleases, incl self-hosted or dedicated ones).

I think something like this would be quite nice:

export const someTask = task({
  id: "some-task",
  machine: "small-2x",
  worker: "us-east-1",
  run: async (payload: any) => {
    logger.info("Hello world");
  },
});

export const someOtherTask = task({
  id: "some-other-task",
  run: async () => {
    logger.info("Hello again");

    await someTask.trigger("foo", { machine: "micro", worker: "eu-central-1" });
  },
});

At the same time, I think there could be some confusion around machine vs worker. There wouldn't be with machine vs region, but it wouldn't necessarily be accurate. What do you think?

@ashleyww93
Copy link

Thank you for this! This will be great for us.

🙌

Is there a reason you went with machinePreset as a option instead of machine: { preset: '' }.
I know the other options in machine are deprecated, but it seems like it would be easier to maintain and document if the type was shared?

Yep, precisely due to the deprecation many months ago when we added v3 billing. Final name TBD and yet to add docs.

There will be some breaking changes to the SDK in the near future. Could be a good time to simplify new options even further, maybe in this case: machine: string

This could go hand in hand with an upcoming option to select the region or "worker group" (internal name for now - there could be multiple groups in the same region, with different features / prereleases, incl self-hosted or dedicated ones).

I think something like this would be quite nice:

export const someTask = task({
  id: "some-task",
  machine: "small-2x",
  worker: "us-east-1",
  run: async (payload: any) => {
    logger.info("Hello world");
  },
});

export const someOtherTask = task({
  id: "some-other-task",
  run: async () => {
    logger.info("Hello again");

    await someTask.trigger("foo", { machine: "micro", worker: "eu-central-1" });
  },
});

At the same time, I think there could be some confusion around machine vs worker. There wouldn't be with machine vs region, but it wouldn't necessarily be accurate. What do you think?

Got it!

I think machine and worker could be confusing for some... region is a pretty standard term these days (aws has more than one eu region for example).

Another option could be:

export const someTask = task({
  id: "some-task",
  runsOn: {
    machine: "small-2x",
    inGroups: ["us-east-1", "uk-south-1"]
  }
  run: async (payload: any) => {
    logger.info("Hello world");
  },
});

@nicktrn
Copy link
Collaborator Author

nicktrn commented Jan 14, 2025

Yeah, after a quick brainstorm I think we'll go with region 👍

Copy link
Member

@matt-aitken matt-aitken left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Brilliant @nicktrn

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants