Skip to content

Improved schedule engine #2174

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 15 commits into from
Jun 17, 2025
Merged

Improved schedule engine #2174

merged 15 commits into from
Jun 17, 2025

Conversation

ericallam
Copy link
Member

No description provided.

Copy link

changeset-bot bot commented Jun 13, 2025

⚠️ No Changeset found

Latest commit: 8ff6af5

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

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

Copy link
Contributor

coderabbitai bot commented Jun 13, 2025

Walkthrough

This change set introduces a major refactor and expansion of the scheduling and worker infrastructure in the codebase, centered around the introduction of a new internal package, @internal/schedule-engine. The schedule engine provides a unified API and worker system for managing and executing scheduled tasks, with support for distributed execution, CRON schedule calculations, and detailed observability. The webapp is updated to integrate with this engine, including new environment variables for schedule worker configuration and Redis connection details. Numerous legacy scheduling and worker service files are deleted or refactored to use the new engine, and worker job enqueuing is standardized through a new commonWorker interface. Several TypeScript configuration and test files are added to support the new package. Additionally, UI components and routes related to deployment indexing retries are removed.

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ 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.
    • Explain this complex logic.
    • 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 explain this code block.
    • @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 explain its main purpose.
    • @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.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

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.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @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: 14

🔭 Outside diff range comments (5)
internal-packages/run-engine/src/engine/types.ts (1)

128-137: 💡 Verification agent

🧩 Analysis chain

Temporal field proliferation – clarify semantics of createdAt vs queuedAt / queueTimestamp

TriggerParams now exposes three very similar timestamps:

  • createdAt
  • queuedAt
  • queueTimestamp

Without a clear contract, callers may set only one of them or confuse their meaning, causing subtle ordering bugs in metrics or deduplication.

Suggest either:

-  createdAt?: Date;
+  /**
+   * Absolute creation time of the *task run* record in the DB.
+   * Prefer `queuedAt` for queue-ing semantics and `queueTimestamp` for
+   * external-system hand-off.  Documented here to avoid ambiguity.
+   */
+  createdAt?: Date;

and add JSDoc for the other two, or fold them into a single canonical field.

Run this to locate all writes to these properties:


🏁 Script executed:

#!/bin/bash
rg -n --pretty $'(createdAt|queuedAt|queueTimestamp)\\s*:' | head

Length of output: 296


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Check for queuedAt and queueTimestamp in TriggerParams type
rg -n "queuedAt" internal-packages/run-engine/src/engine/types.ts || echo "no matches for queuedAt"
rg -n "queueTimestamp" internal-packages/run-engine/src/engine/types.ts || echo "no matches for queueTimestamp"

Length of output: 209


Enhance JSDoc for Temporal Fields in TriggerParams

The three timestamp fields in TriggerParamscreatedAt, queuedAt, and queueTimestamp—currently lack documentation and have subtly different meanings. Please add clear JSDoc comments to each to prevent misuse:

• File: internal-packages/run-engine/src/engine/types.ts
Lines: ~108–137

Suggested diff:

 interface TriggerParams {
+  /**
+   * Absolute creation time of the task-run record in the database.
+   * Use only for DB-side ordering; not for queue sequencing.
+   */
   createdAt?: Date;
+  /**
+   * Time when this run was enqueued in our internal scheduler.
+   * Use for internal queue ordering and deduplication.
+   */
   queuedAt?: Date;
+  /**
+   * Time when the run was handed off to an external system or broker.
+   * Use for external-system metrics and hand-off tracing.
+   */
   queueTimestamp?: Date;
   machine?: MachinePresetName;
   workerId?: string;
   runnerId?: string;
   releaseConcurrency?: boolean;
   runChainState?: RunChainState;
   scheduleId?: string;
   scheduleInstanceId?: string;
 }
apps/webapp/app/v3/services/triggerTaskV1.server.ts (1)

367-372: 🛠️ Refactor suggestion

Same validation gap for options.queueTimestamp

Duplicate the sanity check here (or extract a shared util) to avoid divergent behaviours between V1 and the new engine path.

internal-packages/schedule-engine/tsconfig.test.json (1)

1-22: ⚠️ Potential issue

include misses the actual test folder

Integration tests live in test/, but "include": ["src/**/*.test.ts"] only covers unit tests inside src/.
vitest will still run the file, yet the compiler won’t type-check it, defeating the purpose of this config.

-  "include": ["src/**/*.test.ts"],
+  "include": ["src/**/*.test.ts", "test/**/*.ts"],

Add the glob (or move the tests) to ensure they’re compiled.

apps/webapp/app/v3/services/timeoutDeployment.server.ts (1)

46-63: 🛠️ Refactor suggestion

tx parameter is now unused – drop or use

enqueue() still accepts tx?: PrismaClientOrTransaction but never references it after the refactor to commonWorker.

-static async enqueue(
-  deploymentId: string,
-  fromStatus: string,
-  errorMessage: string,
-  runAt: Date,
-  tx?: PrismaClientOrTransaction
-) {
+static async enqueue(
+  deploymentId: string,
+  fromStatus: string,
+  errorMessage: string,
+  runAt: Date,
+) {

Keeping an unused parameter risks confusion and lint warnings. If transactional enqueue is still required, wire it through commonWorker.enqueue; otherwise remove it.

apps/webapp/app/v3/services/cancelDevSessionRuns.server.ts (1)

93-106: ⚠️ Potential issue

Breaking change: parameter order flipped

enqueue() used to be (options, tx, runAt?).
The new signature (options, runAt?, tx?) silently swaps runAt and tx. Existing call-sites will now pass a Prisma client where a Date is expected, resulting in an invalid availableAt and no transactional context.

Either restore the original ordering or add an overload while deprecating the old one:

-static async enqueue(
-  options: CancelDevSessionRunsServiceOptions,
-  runAt?: Date,
-  tx?: PrismaClientOrTransaction
-) {
+// Preserve old order
+static async enqueue(
+  options: CancelDevSessionRunsServiceOptions,
+  tx?: PrismaClientOrTransaction,
+  runAt?: Date,
+) {

Remember to prefix _tx if it remains unused.

♻️ Duplicate comments (3)
apps/webapp/app/presenters/v3/RunListPresenter.server.ts (1)

182-186: Same clampToNow duplication as in NextRunListPresenter

Please pull this helper from a shared util to keep behaviour consistent across all call-sites and cut maintenance overhead.

internal-packages/schedule-engine/tsconfig.build.json (1)

6-8: Same DOM lib concern as in tsconfig.src.json

Consider trimming the lib array here as well to keep the build output consistent with the runtime environment.

apps/webapp/app/v3/services/triggerTaskV1.server.ts (1)

442-443: Conditionally include createdAt

Apply the same conditional spread pattern here to avoid sending explicit undefined to Prisma.

🧹 Nitpick comments (31)
apps/webapp/app/presenters/v3/NextRunListPresenter.server.ts (2)

192-195: Utility duplication – extract clampToNow

clampToNow is now copy-pasted in at least two presenters. Move it to a small shared util (e.g. ~/utils/date.ts) to avoid divergence and ease testing.

-function clampToNow(date: Date): Date {
-  const now = new Date();
-  return date > now ? now : date;
-}
+import { clampToNow } from "~/utils/date";

206-208: Minor: avoid double DatenumberDate conversions

time.from / time.to are Date objects. You call clampToNow(time.to) (returns Date) and then immediately .getTime(). Consider inlining to keep it obvious:

- to: time.to ? clampToNow(time.to).getTime() : undefined,
+ to: time.to ? Math.min(time.to.getTime(), Date.now()) : undefined,

Purely cosmetic; feel free to skip.

apps/webapp/app/presenters/v3/RunListPresenter.server.ts (1)

291-294: Performance & readability: calculate once

clampToNow(time.to) is evaluated during SQL template construction; for large batches this inside-template computation is negligible, but calculating once improves clarity:

-  time.to
-    ? Prisma.sql`AND tr."createdAt" <= ${clampToNow(time.to).toISOString()}::timestamp`
+  time.to
+    ? Prisma.sql`AND tr."createdAt" <= ${
+        clampToNow(time.to).toISOString()
+      }::timestamp`

Even better after extracting util as suggested above.

internal-packages/schedule-engine/test/setup.ts (1)

1-4: Consider moving global vitest config to vitest.config.* instead of runtime mutation

vi.setConfig({ testTimeout: 60_000 }); works, but:

  1. It executes after test file import order, which can be flaky if other files rely on the timeout earlier.
  2. A vitest.config.ts (or <root>/vitest.setup.ts referenced via setupFiles) is the canonical place.

If you keep this, at least prefix the filename with setupTests. to make its intent clearer.

apps/webapp/app/v3/services/triggerTask.server.ts (1)

34-36: Consider surfacing docs / validation for the new options

queueTimestamp and overrideCreatedAt are accepted here, but nothing verifies that:

  • queueTimestampoverrideCreatedAt (or vice-versa depending on intent)
  • both are sensible (e.g. not in the future or > now + max skew)

A short JSDoc comment or runtime guard would prevent subtle clock-skew bugs.

apps/webapp/app/v3/services/createBackgroundWorker.server.ts (1)

28-29: Import is used only for side-effectful calls – keep tree-shaking friendly

scheduleEngine is imported at module top level but only referenced inside syncDeclarativeSchedules.
For clarity / bundler friendliness you could move the import next to its usage:

-import { scheduleEngine } from "../scheduleEngine.server";
+// defer import to keep the main bundle lean
+import { scheduleEngine } from "../scheduleEngine.server";

(Not critical; feel free to ignore if build size is not a concern.)

internal-packages/schedule-engine/tsconfig.json (1)

1-8: Minor: missing "strict": true & rootDir can hurt DX

Since this is a new package, enabling compiler strictness early saves bugs later:

   "compilerOptions": {
+    "strict": true,
     "moduleResolution": "Node16",
     "module": "Node16",
     "customConditions": ["@triggerdotdev/source"]
   }

Also add "rootDir": "./src" to keep emitted paths tidy.

internal-packages/schedule-engine/tsconfig.src.json (1)

6-8: Unnecessary DOM libs increase type-check noise

The library list includes DOM* libs even though the package runs exclusively in Node. This can:

  • pull in thousands of irrelevant types
  • mask accidental browser-only API usage
-    "lib": ["ES2020", "DOM", "DOM.Iterable", "DOM.AsyncIterable"],
+    "lib": ["ES2020"],

Unless you intentionally reference browser globals inside the engine, dropping them will speed up builds and tighten type safety.

apps/webapp/app/runEngine/services/triggerTask.server.ts (1)

311-312: Passing createdAt as undefined clutters the Prisma payload

createdAt is always present in the object, even when no override is supplied. Prisma accepts undefined, but it still bloats query text and hides intent.

Consider making the property conditional:

-                  createdAt: options.overrideCreatedAt,
+                  ...(options.overrideCreatedAt
+                    ? { createdAt: options.overrideCreatedAt }
+                    : {}),

Keeps the payload minimal and future-proof if Prisma tightens strict-null-checks.

internal-packages/schedule-engine/src/engine/workerCatalog.ts (1)

3-14: Explicit typing & as const would safeguard the catalog

scheduleWorkerCatalog is currently an untyped object literal. Down-stream code will lose IntelliSense and accidental property changes won’t be caught.

-export const scheduleWorkerCatalog = {
+import type { WorkerCatalog } from "@trigger.dev/worker"; // hypothetical shared type
+
+export const scheduleWorkerCatalog: WorkerCatalog = {
   "schedule.triggerScheduledTask": {
     schema: z.object({
       instanceId: z.string(),
       exactScheduleTime: z.coerce.date(),
     }),

Optionally append as const after the object to freeze the keys.

This minor change prevents typos (e.g., "schedule.triggerSchedueldTask") from compiling.

apps/webapp/app/services/email.server.ts (1)

95-101: Return the enqueue promise to surface failures

scheduleEmail currently awaits the enqueue but returns void, swallowing any value the worker library might provide (job id, etc.). Returning the promise enables callers to react or log the job id.

-export async function scheduleEmail(data: DeliverEmail, delay?: { seconds: number }) {
+export async function scheduleEmail(
+  data: DeliverEmail,
+  delay?: { seconds: number }
+): Promise<void> {
   const availableAt = delay ? new Date(Date.now() + delay.seconds * 1000) : undefined;
-  await commonWorker.enqueue({
+  return commonWorker.enqueue({
     job: "scheduleEmail",
     payload: data,
     availableAt,
   });
 }

Also consider validating delay.seconds >= 0 to avoid accidental past dates.

internal-packages/schedule-engine/src/engine/distributedScheduling.ts (1)

21-26: Small clarity nit

Math.pow(2, 31) can be replaced with the more idiomatic 2 ** 31, which is easier to read and avoids an extra function call.

apps/webapp/app/v3/commonWorker.server.ts (1)

48-141: Catalog definition is getting unwieldy

Hard-coding dozens of job specs with identical visibilityTimeoutMs and very similar retry policies makes maintenance painful. Consider extracting helpers:

const defaultJob = <T>(schema: T, retry = 5) => ({
  schema,
  visibilityTimeoutMs: 60_000,
  retry: { maxAttempts: retry },
});

Then:

catalog: {
  "v3.resumeBatchRun": defaultJob(z.object({ batchRunId: z.string() })),
  ...
}

This trims ~150 LOC and reduces copy-paste errors.

internal-packages/schedule-engine/README.md (2)

51-58: Minor wording & brevity nit

“from executing at exactly the same moment”

-Prevents thundering herd issues by distributing executions across time windows
+Prevents thundering-herd issues by spreading executions across a time window
🧰 Tools
🪛 LanguageTool

[style] ~51-~51: ‘exactly the same’ might be wordy. Consider a shorter alternative.
Context: ...t all scheduled tasks from executing at exactly the same moment: ```typescript import { calcula...

(EN_WORDINESS_PREMIUM_EXACTLY_THE_SAME)


101-105: Dangling colon renders as loose punctuation

A colon at the start of a bullet occasionally shows up in some markdown renderers:

-- `redis`: Redis connection configuration
++ `redis` – Redis connection configuration
🧰 Tools
🪛 LanguageTool

[uncategorized] ~101-~101: Loose punctuation mark.
Context: ...these configuration options: - prisma: PrismaClient instance - redis: Redis ...

(UNLIKELY_OPENING_PUNCTUATION)

apps/webapp/app/v3/services/timeoutDeployment.server.ts (1)

53-62: Consider enqueueOnce to avoid duplicate timeout jobs

Timeouts are idempotent; using plain enqueue can queue duplicates if enqueue is called multiple times before the first job is processed.

- await commonWorker.enqueue({
+ await commonWorker.enqueueOnce({
   id: `timeoutDeployment:${deploymentId}`,

The unique id is already provided, so switching to enqueueOnce protects against accidental duplication at no extra cost.

apps/webapp/app/v3/services/executeTasksWaitingForDeploy.ts (1)

107-116: Use enqueueOnce for id-based deduplication

As with the timeout service, the job ID is deterministic (v3.executeTasksWaitingForDeploy:${backgroundWorkerId}).
Switching to enqueueOnce guarantees exactly-once semantics during bursts (e.g., multiple deploy hooks firing).

- return await commonWorker.enqueue({
+ return await commonWorker.enqueueOnce({
apps/webapp/app/v3/services/cancelTaskAttemptDependencies.server.ts (1)

60-69: Unused tx parameter – silence linter or drop it

The tx argument is no longer forwarded to commonWorker.enqueue, leaving it unused and triggering the @typescript-eslint/no-unused-vars rule in most code-bases.

-static async enqueue(attemptId: string, tx: PrismaClientOrTransaction, runAt?: Date) {
+static async enqueue(
+  attemptId: string,
+  _tx: PrismaClientOrTransaction, // keep positional compatibility but silence linter
+  runAt?: Date
+) {

If transactions are no longer required here, consider making the parameter optional and prefixing with an underscore (or removing it entirely) across call-sites to avoid confusion.

apps/webapp/app/runEngine/services/batchTrigger.server.ts (1)

316-321: tx parameter kept but never used

#enqueueBatchTaskRun() still accepts a tx parameter yet the value is ignored after the switch to commonWorker.enqueue. Either remove the parameter or rename it to _tx to clarify that it is intentionally unused:

-async #enqueueBatchTaskRun(options: BatchProcessingOptions, tx?: PrismaClientOrTransaction) {
+async #enqueueBatchTaskRun(options: BatchProcessingOptions, _tx?: PrismaClientOrTransaction) {

Cleaning this up avoids false expectations that the call will be wrapped in a transaction.

apps/webapp/app/v3/services/resumeTaskDependency.server.ts (1)

157-171: Unused tx argument

Similar to other services, tx is accepted but not used after the move to commonWorker.enqueue.

-static async enqueue(
-  dependencyId: string,
-  sourceTaskAttemptId: string,
-  tx: PrismaClientOrTransaction,
-  runAt?: Date
-) {
+static async enqueue(
+  dependencyId: string,
+  sourceTaskAttemptId: string,
+  _tx: PrismaClientOrTransaction,
+  runAt?: Date
+) {

This prevents linter warnings and signals that transactional support has been removed.

apps/webapp/test/distributedScheduling.test.ts (1)

57-88: Potential flakiness in uniform-distribution assertion

The “should distribute work evenly” test uses 1 000 samples and fails if fewer than 80 % of 30 buckets receive at least one hit.
While unlikely, the deterministic hash could still cluster enough samples to dip below the 24-bucket threshold, making the test flaky.

Consider loosening the assertion or increasing the sample size:

-const testCount = 1000;
-
-expect(bucketsWithItems).toBeGreaterThan(distributionWindow * 0.8);
+const testCount = 5_000; // reduces variance
+
+expect(bucketsWithItems).toBeGreaterThan(distributionWindow * 0.7);

This keeps the spirit of the check while minimising spurious CI failures.

apps/webapp/app/v3/services/resumeBatchRun.server.ts (1)

2-2: Unused import side-effect

Switching to commonWorker makes the PrismaClientOrTransaction argument in enqueue() obsolete. Consider pruning that parameter from the method signature (and its call-sites) to avoid dead code and confusion.

apps/webapp/app/v3/scheduleEngine.server.ts (1)

81-116: Error is swallowed – add structured logging

The catch only returns { success:false } but drops stack traces; production debugging will be painful.

-      } catch (error) {
-        return {
-          success: false,
-          error: error instanceof Error ? error.message : String(error),
-        };
+      } catch (error) {
+        logger.error("scheduleEngine.onTriggerScheduledTask failed", { error });
+        return {
+          success: false,
+          error: error instanceof Error ? error.message : String(error),
+        };
       }
apps/webapp/app/v3/services/batchTriggerV3.server.ts (2)

478-540: Inconsistent logging & IDs reference “V2”

This v3 service logs under BatchTriggerV2 and builds job IDs with BatchTriggerV2Service.process.
Rename to BatchTriggerV3 to avoid future grep/debug headaches.

- id: `BatchTriggerV2Service.process:${options.batchId}:${options.processingId}`,
+ id: `BatchTriggerV3Service.process:${options.batchId}:${options.processingId}`,

Same for every logger.debug message using [BatchTriggerV2] ….


895-899: tx parameter is never used

#enqueueBatchTaskRun still accepts tx but ignores it. Drop the argument or forward it to a transactional queue helper; leaving it dangling is misleading.

internal-packages/schedule-engine/test/scheduleEngine.test.ts (1)

121-123: Avoid brittle exact-equality on Date

expect(actualNextExecution).toEqual(expectedExecutionTime) can flake by a few ms.
Use a ±1 s window or toBeCloseTo with a tolerance instead.

internal-packages/schedule-engine/src/engine/types.ts (1)

27-30: Constrain logLevel via a union

logLevel?: string accepts invalid values at runtime. Consider

logLevel?: "log" | "error" | "warn" | "info" | "debug";

This mirrors the enum you use elsewhere and prevents typos.

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

108-128: Parallelise instance creation / registration

The loop issues a Prisma insert then immediately waits for scheduleEngine.registerNextTaskScheduleInstance.
With many environments this becomes O(n) sequential I/O. Consider:

await Promise.all(
  options.environments.map(async (environmentId) => {
    const instance = await this._prisma.taskScheduleInstance.create({});
    await scheduleEngine.registerNextTaskScheduleInstance({ instanceId: instance.id });
  })
);

This keeps semantic order while cutting latency substantially.


206-218: Typo & readability

instancesToDeletedinstancesToDelete. Minor, but avoiding grammatical slips helps future readers.

internal-packages/schedule-engine/src/engine/index.ts (1)

96-106: Side-effects in constructor hinder testability

Spawning the worker inside the constructor (this.worker.start()) means merely importing / instantiating the class connects to Redis and spawns threads, complicating unit tests and life-cycle management.
Expose an explicit start() method instead; call it from your singleton wrapper.

apps/webapp/app/env.server.ts (1)

686-695: Clarify overlapping concurrency env-vars

The trio
SCHEDULE_WORKER_CONCURRENCY_WORKERS,
SCHEDULE_WORKER_CONCURRENCY_TASKS_PER_WORKER, and
SCHEDULE_WORKER_CONCURRENCY_LIMIT
overlap but the codebase only reads concurrency (workers × tasks). Document which flags are authoritative or drop the unused ones to avoid misconfiguration.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 8a5e7f3 and 177f59d.

⛔ Files ignored due to path filters (2)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
  • references/hello-world/src/trigger/schedule.ts is excluded by !references/**
📒 Files selected for processing (49)
  • apps/webapp/app/env.server.ts (1 hunks)
  • apps/webapp/app/presenters/v3/NextRunListPresenter.server.ts (2 hunks)
  • apps/webapp/app/presenters/v3/RunListPresenter.server.ts (2 hunks)
  • apps/webapp/app/runEngine/services/batchTrigger.server.ts (2 hunks)
  • apps/webapp/app/runEngine/services/triggerTask.server.ts (1 hunks)
  • apps/webapp/app/services/email.server.ts (2 hunks)
  • apps/webapp/app/services/runsRepository.server.ts (1 hunks)
  • apps/webapp/app/services/worker.server.ts (19 hunks)
  • apps/webapp/app/v3/commonWorker.server.ts (3 hunks)
  • apps/webapp/app/v3/scheduleEngine.server.ts (1 hunks)
  • apps/webapp/app/v3/services/batchTriggerV3.server.ts (3 hunks)
  • apps/webapp/app/v3/services/cancelDevSessionRuns.server.ts (2 hunks)
  • apps/webapp/app/v3/services/cancelTaskAttemptDependencies.server.ts (2 hunks)
  • apps/webapp/app/v3/services/changeCurrentDeployment.server.ts (1 hunks)
  • apps/webapp/app/v3/services/createBackgroundWorker.server.ts (3 hunks)
  • apps/webapp/app/v3/services/createDeploymentBackgroundWorkerV3.server.ts (1 hunks)
  • apps/webapp/app/v3/services/executeTasksWaitingForDeploy.ts (2 hunks)
  • apps/webapp/app/v3/services/registerNextTaskScheduleInstance.server.ts (0 hunks)
  • apps/webapp/app/v3/services/resumeBatchRun.server.ts (2 hunks)
  • apps/webapp/app/v3/services/resumeTaskDependency.server.ts (2 hunks)
  • apps/webapp/app/v3/services/resumeTaskRunDependencies.server.ts (2 hunks)
  • apps/webapp/app/v3/services/retryAttempt.server.ts (2 hunks)
  • apps/webapp/app/v3/services/timeoutDeployment.server.ts (2 hunks)
  • apps/webapp/app/v3/services/triggerScheduledTask.server.ts (0 hunks)
  • apps/webapp/app/v3/services/triggerTask.server.ts (1 hunks)
  • apps/webapp/app/v3/services/triggerTaskV1.server.ts (2 hunks)
  • apps/webapp/app/v3/services/upsertTaskSchedule.server.ts (4 hunks)
  • apps/webapp/app/v3/utils/distributedScheduling.server.ts (1 hunks)
  • apps/webapp/package.json (1 hunks)
  • apps/webapp/test/distributedScheduling.test.ts (1 hunks)
  • internal-packages/run-engine/src/engine/index.ts (2 hunks)
  • internal-packages/run-engine/src/engine/types.ts (1 hunks)
  • internal-packages/schedule-engine/README.md (1 hunks)
  • internal-packages/schedule-engine/package.json (1 hunks)
  • internal-packages/schedule-engine/src/engine/distributedScheduling.ts (1 hunks)
  • internal-packages/schedule-engine/src/engine/index.ts (1 hunks)
  • internal-packages/schedule-engine/src/engine/scheduleCalculation.ts (1 hunks)
  • internal-packages/schedule-engine/src/engine/types.ts (1 hunks)
  • internal-packages/schedule-engine/src/engine/workerCatalog.ts (1 hunks)
  • internal-packages/schedule-engine/src/index.ts (1 hunks)
  • internal-packages/schedule-engine/test/scheduleEngine.test.ts (1 hunks)
  • internal-packages/schedule-engine/test/setup.ts (1 hunks)
  • internal-packages/schedule-engine/tsconfig.build.json (1 hunks)
  • internal-packages/schedule-engine/tsconfig.json (1 hunks)
  • internal-packages/schedule-engine/tsconfig.src.json (1 hunks)
  • internal-packages/schedule-engine/tsconfig.test.json (1 hunks)
  • internal-packages/schedule-engine/vitest.config.ts (1 hunks)
  • packages/redis-worker/src/worker.ts (1 hunks)
  • packages/rsc/src/package.json (1 hunks)
💤 Files with no reviewable changes (2)
  • apps/webapp/app/v3/services/registerNextTaskScheduleInstance.server.ts
  • apps/webapp/app/v3/services/triggerScheduledTask.server.ts
🧰 Additional context used
🧬 Code Graph Analysis (15)
apps/webapp/app/v3/services/changeCurrentDeployment.server.ts (1)
apps/webapp/app/v3/services/executeTasksWaitingForDeploy.ts (1)
  • ExecuteTasksWaitingForDeployService (8-117)
apps/webapp/app/v3/services/createDeploymentBackgroundWorkerV3.server.ts (1)
apps/webapp/app/v3/services/executeTasksWaitingForDeploy.ts (1)
  • ExecuteTasksWaitingForDeployService (8-117)
apps/webapp/app/v3/services/resumeTaskRunDependencies.server.ts (1)
apps/webapp/app/v3/commonWorker.server.ts (1)
  • commonWorker (279-279)
apps/webapp/app/services/email.server.ts (2)
apps/webapp/app/v3/commonWorker.server.ts (1)
  • commonWorker (279-279)
internal-packages/emails/src/index.tsx (1)
  • data (80-122)
apps/webapp/app/v3/services/executeTasksWaitingForDeploy.ts (1)
apps/webapp/app/v3/commonWorker.server.ts (1)
  • commonWorker (279-279)
apps/webapp/app/v3/services/timeoutDeployment.server.ts (3)
apps/webapp/app/v3/commonWorker.server.ts (1)
  • commonWorker (279-279)
apps/webapp/app/db.server.ts (1)
  • PrismaClientOrTransaction (21-21)
apps/webapp/app/services/worker.server.ts (1)
  • workerQueue (373-373)
apps/webapp/app/v3/services/cancelTaskAttemptDependencies.server.ts (1)
apps/webapp/app/v3/commonWorker.server.ts (1)
  • commonWorker (279-279)
packages/redis-worker/src/worker.ts (2)
internal-packages/schedule-engine/src/engine/index.ts (1)
  • JobHandlerParams (217-225)
internal-packages/zod-worker/src/index.ts (1)
  • K (581-660)
apps/webapp/app/v3/services/retryAttempt.server.ts (1)
apps/webapp/app/v3/commonWorker.server.ts (1)
  • commonWorker (279-279)
internal-packages/schedule-engine/src/engine/types.ts (4)
internal-packages/schedule-engine/src/index.ts (3)
  • TriggerScheduledTaskCallback (5-5)
  • ScheduleEngineOptions (3-3)
  • TriggerScheduleParams (4-4)
apps/webapp/app/db.server.ts (1)
  • PrismaClient (228-228)
internal-packages/redis/src/index.ts (1)
  • RedisOptions (4-4)
internal-packages/tracing/src/index.ts (2)
  • Tracer (14-14)
  • Meter (16-16)
apps/webapp/app/v3/services/resumeTaskDependency.server.ts (1)
apps/webapp/app/v3/commonWorker.server.ts (1)
  • commonWorker (279-279)
apps/webapp/test/distributedScheduling.test.ts (1)
apps/webapp/app/v3/utils/distributedScheduling.server.ts (1)
  • calculateDistributedExecutionTime (6-31)
apps/webapp/app/v3/services/cancelDevSessionRuns.server.ts (2)
apps/webapp/app/v3/commonWorker.server.ts (1)
  • commonWorker (279-279)
apps/webapp/app/v3/services/batchTriggerV3.server.ts (1)
  • options (894-900)
apps/webapp/app/v3/services/resumeBatchRun.server.ts (1)
apps/webapp/app/v3/commonWorker.server.ts (1)
  • commonWorker (279-279)
apps/webapp/app/v3/services/createBackgroundWorker.server.ts (1)
apps/webapp/app/v3/scheduleEngine.server.ts (1)
  • scheduleEngine (11-11)
🪛 LanguageTool
internal-packages/schedule-engine/README.md

[style] ~51-~51: ‘exactly the same’ might be wordy. Consider a shorter alternative.
Context: ...t all scheduled tasks from executing at exactly the same moment: ```typescript import { calcula...

(EN_WORDINESS_PREMIUM_EXACTLY_THE_SAME)


[uncategorized] ~101-~101: Loose punctuation mark.
Context: ...these configuration options: - prisma: PrismaClient instance - redis: Redis ...

(UNLIKELY_OPENING_PUNCTUATION)

⏰ Context from checks skipped due to timeout of 90000ms (25)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (1, 10)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (8, 10)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (10, 10)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (7, 10)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (4, 10)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (6, 10)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (9, 10)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (3, 10)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (5, 10)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (2, 10)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (8, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (7, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (4, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (3, 8)
  • GitHub Check: units / packages / 🧪 Unit Tests: Packages (1, 1)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (2, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (1, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (6, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (5, 8)
  • GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - pnpm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - npm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - pnpm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - npm)
  • GitHub Check: typecheck / typecheck
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (16)
packages/rsc/src/package.json (1)

1-3: Minimal package.json LGTM, but double-check directory purpose

Declaring "type": "module" is fine and consistent with the rest of the repo.
Make sure:

  1. No other package.json higher in the packages/rsc tree overrides this.
  2. Tooling that consumes this folder (ts-node, vitest, etc.) expects ESM.

If both are already covered, nothing else to do here.

apps/webapp/package.json (1)

53-57: Workspace dependency added – ensure pipeline & lockfile are updated

"@internal/schedule-engine": "workspace:*" looks correct.
Please run the package-manager install (pnpm install / npm install -w) and commit the updated lockfile so CI picks it up.

apps/webapp/app/v3/services/changeCurrentDeployment.server.ts (1)

87-87: Call site now matches new enqueue signature – all good

ExecuteTasksWaitingForDeployService.enqueue now only accepts (backgroundWorkerId, runAt?).
This update removes the stale Prisma argument and compiles cleanly.

apps/webapp/app/v3/services/createDeploymentBackgroundWorkerV3.server.ts (1)

164-166: LGTM – signature change reflected correctly

ExecuteTasksWaitingForDeployService.enqueue no longer requires the Prisma client, and the call site has been updated accordingly.

apps/webapp/app/v3/services/createBackgroundWorker.server.ts (1)

571-573: Error propagation unchanged but worth revisiting

scheduleEngine.registerNextTaskScheduleInstance is awaited inside this tight loop.
If that call throws (e.g. transient Redis issue) the entire worker-creation flow aborts and rolls back the DB transaction – the same behaviour the removed service had, but now the failure surface is broader (Redis, distributed locks…).

Consider wrapping in a retry helper or catching and logging non-fatal errors to avoid making deployments brittle.

Also applies to: 603-604

internal-packages/schedule-engine/vitest.config.ts (1)

11-13: Confirm the esbuild target is aligned with runtime

target: "node18" is fine today, but if the runtime matrix includes Node 20 (current LTS) the emitted code will miss out on native improvements (e.g., fetch, structuredClone). Worth double-checking the production containers.

internal-packages/schedule-engine/src/index.ts (1)

1-6: Public entry-point looks good

The minimalist barrel file is clear and follows the Node16/ESM convention that the compiler will emit .js files, so the explicit .js extension is appropriate. No further concerns.

apps/webapp/app/v3/services/resumeTaskRunDependencies.server.ts (1)

8-9: Import change looks correct

Switching to the new commonWorker aligns with the broader refactor.

apps/webapp/app/services/email.server.ts (1)

7-8: Import update acknowledged

Migrating to commonWorker is consistent with the rest of the PR.

internal-packages/schedule-engine/package.json (1)

8-14: Non-standard export key

"@triggerdotdev/source" inside exports isn’t a recognised condition and may break resolution in Node ≥16. Verify that tools relying on this key actually support it; otherwise use a documented condition such as "source" or "development".

apps/webapp/app/v3/commonWorker.server.ts (1)

188-195: Ensure numeric env values

pollIntervalMs, immediatePollIntervalMs, worker counts, etc., are passed straight from env.*. Confirm the Zod schema parses them to numbers; if they are still strings, RedisWorker will treat "5000" as a string and mis-handle arithmetic/timeouts.

If parsing isn’t already done in env.server.ts, coerce here:

pollIntervalMs: Number(env.COMMON_WORKER_POLL_INTERVAL),
apps/webapp/app/services/worker.server.ts (1)

238-246: Confirm finalAttempt semantics against worker implementation

finalAttempt is derived from job.attempts === job.max_attempts.
In graphile-worker the attempts counter already includes the current attempt, so the flag will be true while the job is still running, not after it has finally failed.
If scheduleEngine.triggerScheduledTask() internally interprets finalAttempt as “no more retries will follow”, this could lead to premature deletion / alerting.

await scheduleEngine.triggerScheduledTask({
  instanceId: payload.instanceId,
  finalAttempt: job.attempts === job.max_attempts, // ← verify semantics
});

Please double-check the contract and adjust to job.attempts + 1 === job.max_attempts (or similar) if the engine expects the next attempt to be the last.

apps/webapp/app/v3/services/timeoutDeployment.server.ts (1)

66-69: Acknowledge both queues symmetrically

dequeue is invoked on workerQueue, while ack is invoked on commonWorker.
If workerQueue.dequeue() fails (e.g., job not found) the commonWorker.ack() will still run, silently discarding the job in the new queue. Consider guarding with an existence check or catching errors to keep behaviour predictable during the migration window.

packages/redis-worker/src/worker.ts (1)

37-48: Type extraction looks good

Extracting JobHandlerParams makes handler definitions clearer and reusable; compile-time inference also improves.

apps/webapp/app/v3/services/resumeBatchRun.server.ts (1)

337-344: Verify availableAt semantics

commonWorker.enqueue often expects a Unix epoch (ms) whereas you’re passing a Date | undefined.
Double-check the worker’s API – if it expects a number, wrap with .getTime(); if it accepts Date, ignore this note.

internal-packages/schedule-engine/src/engine/scheduleCalculation.ts (1)

22-30: LGTM – cron calculation is concise and correct

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: 0

🧹 Nitpick comments (3)
apps/webapp/app/v3/commonWorker.server.ts (3)

127-154: Two almost-identical job definitions may lead to accidental drift

"v3.processBatchTaskRun" and "runengine.processBatchTaskRun" repeat the same schema/timeout/retry logic, differing only by a couple of optional fields.
If both names are required, consider:

  1. Creating a shared BatchTaskRunSchema and spreading it into both entries to avoid silent divergence later.
  2. Verifying that downstream producers/consumers consistently pick the intended key – the similarity makes copy-paste mistakes easy.

Let me know if you’d like a quick refactor snippet.


42-49: DeliverEmailSchema is imported but never reused in the handler

The catalog entry validates against DeliverEmailSchema, yet the handler receives payload untyped (any).
Annotating the handler parameter tightens compile-time safety:

-import { DeliverEmailSchema } from "emails";
+import { DeliverEmailSchema, type DeliverEmail } from "emails";-  scheduleEmail: async ({ payload }) => {
-    await sendEmail(payload);
+  scheduleEmail: async ({ payload }) => {
+    const email: DeliverEmail = payload; // satisfies schema
+    await sendEmail(email);
   },

This prevents accidental misuse of the payload object.

Also applies to: 211-214


78-87: Constant-ify the ubiquitous visibilityTimeoutMs: 60_000 / maxAttempts

The same magic numbers reappear in every catalog entry. Extracting small helpers (e.g. const ONE_MINUTE = 60_000) or a factory function improves readability and makes global tuning trivial.

Also applies to: 112-114, 136-138, 150-154

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 177f59d and 68375fc.

📒 Files selected for processing (2)
  • apps/webapp/app/v3/commonWorker.server.ts (3 hunks)
  • packages/redis-worker/src/queue.ts (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • packages/redis-worker/src/queue.ts
⏰ Context from checks skipped due to timeout of 90000ms (25)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (2, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (4, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (7, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (8, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (5, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (6, 8)
  • GitHub Check: units / packages / 🧪 Unit Tests: Packages (1, 1)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (3, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (1, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (9, 10)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (8, 10)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (5, 10)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (7, 10)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (10, 10)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (2, 10)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (4, 10)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (6, 10)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (1, 10)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (3, 10)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - npm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - npm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - pnpm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - pnpm)
  • GitHub Check: typecheck / typecheck
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (1)
apps/webapp/app/v3/commonWorker.server.ts (1)

201-205:

❌ Incorrect review comment

Convert concurrency env values to numbers before passing to the worker

env variables are string | undefined. RedisWorker’s concurrency options expect numbers; handing it strings risks implicit coercion bugs when the library does arithmetic (e.g. Math.min). Parse once at the boundary:

-  concurrency: {
-    workers: env.COMMON_WORKER_CONCURRENCY_WORKERS,
-    tasksPerWorker: env.COMMON_WORKER_CONCURRENCY_TASKS_PER_WORKER,
-    limit: env.COMMON_WORKER_CONCURRENCY_LIMIT,
-  },
+  concurrency: {
+    workers: Number(env.COMMON_WORKER_CONCURRENCY_WORKERS),
+    tasksPerWorker: Number(env.COMMON_WORKER_CONCURRENCY_TASKS_PER_WORKER),
+    limit: Number(env.COMMON_WORKER_CONCURRENCY_LIMIT),
+  },

🏁 Script executed:

#!/bin/bash
set -e

echo "🔍 Searching for concurrency env vars in schema:"
rg -n "COMMON_WORKER_CONCURRENCY_WORKERS" -n .

echo "🔍 Locating where `env` is exported:"
rg -n "export const env" -n .

Length of output: 2457


🏁 Script executed:

#!/bin/bash
set -e

echo "🔍 Checking tasksPerWorker schema definition:"
rg -n "COMMON_WORKER_CONCURRENCY_TASKS_PER_WORKER" apps/webapp/app/env.server.ts

echo "🔍 Checking limit schema definition:"
rg -n "COMMON_WORKER_CONCURRENCY_LIMIT" apps/webapp/app/env.server.ts

Length of output: 507


🏁 Script executed:

#!/bin/bash
set -e

echo "🔍 Showing import statements in commonWorker.server.ts:"
sed -n '1,50p' apps/webapp/app/v3/commonWorker.server.ts | grep -E "^import .*env"

Length of output: 248


No conversion needed: concurrency env vars are already numbers
The env import comes from EnvironmentSchema.parse(process.env), where these keys use z.coerce.number().int().default(...). That guarantees env.COMMON_WORKER_CONCURRENCY_* are typed and parsed as number, so wrapping them in Number(…) is redundant.

No changes required.

Likely an incorrect or invalid review comment.

@ericallam ericallam force-pushed the cursor-schedule-worker-redis branch from 68375fc to 42c3f51 Compare June 15, 2025 19:02
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

♻️ Duplicate comments (2)
internal-packages/schedule-engine/src/engine/index.ts (2)

42-42: Unsafe tracer fallback still present
Casting startSpan to any to extract .tracer defeats type-safety and risks breaking when the tracing util changes. Provide the tracer via options.tracer or an explicit getTracer() helper instead.


608-609: Job-ID collision risk remains
id: \scheduled-task-instance:${instanceId}`` is reused for every run; pending or stalled jobs with the same ID will cause enqueue failures or silent overwrites.
Include a unique component (timestamp or counter) in the ID.

🧹 Nitpick comments (2)
internal-packages/schedule-engine/src/engine/index.ts (1)

90-90: Hard-coded “debug” logger level for worker
The worker always uses a new Logger("ScheduleEngineWorker", "debug"), ignoring the engine’s configured log level.
Pass the chosen level (or the existing logger instance) to avoid noisy logs in production.

internal-packages/schedule-engine/README.md (1)

51-57: Minor wording nitpick
“executing at exactly the same moment” → “executing simultaneously” is shorter and clearer.

🧰 Tools
🪛 LanguageTool

[style] ~51-~51: ‘exactly the same’ might be wordy. Consider a shorter alternative.
Context: ...t all scheduled tasks from executing at exactly the same moment: ```typescript import { calcula...

(EN_WORDINESS_PREMIUM_EXACTLY_THE_SAME)

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 68375fc and 42c3f51.

⛔ Files ignored due to path filters (2)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
  • references/hello-world/src/trigger/schedule.ts is excluded by !references/**
📒 Files selected for processing (50)
  • apps/webapp/app/env.server.ts (1 hunks)
  • apps/webapp/app/presenters/v3/NextRunListPresenter.server.ts (2 hunks)
  • apps/webapp/app/presenters/v3/RunListPresenter.server.ts (2 hunks)
  • apps/webapp/app/runEngine/services/batchTrigger.server.ts (2 hunks)
  • apps/webapp/app/runEngine/services/triggerTask.server.ts (1 hunks)
  • apps/webapp/app/services/email.server.ts (2 hunks)
  • apps/webapp/app/services/runsRepository.server.ts (1 hunks)
  • apps/webapp/app/services/worker.server.ts (19 hunks)
  • apps/webapp/app/v3/commonWorker.server.ts (3 hunks)
  • apps/webapp/app/v3/scheduleEngine.server.ts (1 hunks)
  • apps/webapp/app/v3/services/batchTriggerV3.server.ts (3 hunks)
  • apps/webapp/app/v3/services/cancelDevSessionRuns.server.ts (2 hunks)
  • apps/webapp/app/v3/services/cancelTaskAttemptDependencies.server.ts (2 hunks)
  • apps/webapp/app/v3/services/changeCurrentDeployment.server.ts (1 hunks)
  • apps/webapp/app/v3/services/createBackgroundWorker.server.ts (3 hunks)
  • apps/webapp/app/v3/services/createDeploymentBackgroundWorkerV3.server.ts (1 hunks)
  • apps/webapp/app/v3/services/executeTasksWaitingForDeploy.ts (2 hunks)
  • apps/webapp/app/v3/services/registerNextTaskScheduleInstance.server.ts (0 hunks)
  • apps/webapp/app/v3/services/resumeBatchRun.server.ts (2 hunks)
  • apps/webapp/app/v3/services/resumeTaskDependency.server.ts (2 hunks)
  • apps/webapp/app/v3/services/resumeTaskRunDependencies.server.ts (2 hunks)
  • apps/webapp/app/v3/services/retryAttempt.server.ts (2 hunks)
  • apps/webapp/app/v3/services/timeoutDeployment.server.ts (2 hunks)
  • apps/webapp/app/v3/services/triggerScheduledTask.server.ts (0 hunks)
  • apps/webapp/app/v3/services/triggerTask.server.ts (1 hunks)
  • apps/webapp/app/v3/services/triggerTaskV1.server.ts (2 hunks)
  • apps/webapp/app/v3/services/upsertTaskSchedule.server.ts (4 hunks)
  • apps/webapp/app/v3/utils/distributedScheduling.server.ts (1 hunks)
  • apps/webapp/package.json (1 hunks)
  • apps/webapp/test/distributedScheduling.test.ts (1 hunks)
  • internal-packages/run-engine/src/engine/index.ts (2 hunks)
  • internal-packages/run-engine/src/engine/types.ts (1 hunks)
  • internal-packages/schedule-engine/README.md (1 hunks)
  • internal-packages/schedule-engine/package.json (1 hunks)
  • internal-packages/schedule-engine/src/engine/distributedScheduling.ts (1 hunks)
  • internal-packages/schedule-engine/src/engine/index.ts (1 hunks)
  • internal-packages/schedule-engine/src/engine/scheduleCalculation.ts (1 hunks)
  • internal-packages/schedule-engine/src/engine/types.ts (1 hunks)
  • internal-packages/schedule-engine/src/engine/workerCatalog.ts (1 hunks)
  • internal-packages/schedule-engine/src/index.ts (1 hunks)
  • internal-packages/schedule-engine/test/scheduleEngine.test.ts (1 hunks)
  • internal-packages/schedule-engine/test/setup.ts (1 hunks)
  • internal-packages/schedule-engine/tsconfig.build.json (1 hunks)
  • internal-packages/schedule-engine/tsconfig.json (1 hunks)
  • internal-packages/schedule-engine/tsconfig.src.json (1 hunks)
  • internal-packages/schedule-engine/tsconfig.test.json (1 hunks)
  • internal-packages/schedule-engine/vitest.config.ts (1 hunks)
  • packages/redis-worker/src/queue.ts (1 hunks)
  • packages/redis-worker/src/worker.ts (1 hunks)
  • packages/rsc/src/package.json (1 hunks)
💤 Files with no reviewable changes (2)
  • apps/webapp/app/v3/services/registerNextTaskScheduleInstance.server.ts
  • apps/webapp/app/v3/services/triggerScheduledTask.server.ts
✅ Files skipped from review due to trivial changes (2)
  • internal-packages/schedule-engine/src/index.ts
  • internal-packages/schedule-engine/src/engine/scheduleCalculation.ts
🚧 Files skipped from review as they are similar to previous changes (44)
  • packages/rsc/src/package.json
  • internal-packages/run-engine/src/engine/types.ts
  • internal-packages/schedule-engine/test/setup.ts
  • apps/webapp/package.json
  • apps/webapp/app/v3/services/changeCurrentDeployment.server.ts
  • internal-packages/schedule-engine/tsconfig.json
  • apps/webapp/app/v3/services/createBackgroundWorker.server.ts
  • apps/webapp/app/v3/services/triggerTask.server.ts
  • apps/webapp/app/v3/services/createDeploymentBackgroundWorkerV3.server.ts
  • packages/redis-worker/src/queue.ts
  • apps/webapp/app/runEngine/services/triggerTask.server.ts
  • internal-packages/schedule-engine/vitest.config.ts
  • apps/webapp/app/services/runsRepository.server.ts
  • internal-packages/schedule-engine/tsconfig.src.json
  • apps/webapp/app/presenters/v3/NextRunListPresenter.server.ts
  • internal-packages/schedule-engine/tsconfig.build.json
  • apps/webapp/app/v3/services/resumeTaskRunDependencies.server.ts
  • apps/webapp/app/services/email.server.ts
  • internal-packages/schedule-engine/tsconfig.test.json
  • apps/webapp/app/v3/services/triggerTaskV1.server.ts
  • apps/webapp/app/v3/utils/distributedScheduling.server.ts
  • apps/webapp/app/services/worker.server.ts
  • apps/webapp/app/presenters/v3/RunListPresenter.server.ts
  • apps/webapp/app/v3/services/cancelTaskAttemptDependencies.server.ts
  • apps/webapp/app/v3/services/timeoutDeployment.server.ts
  • internal-packages/schedule-engine/src/engine/workerCatalog.ts
  • internal-packages/schedule-engine/package.json
  • internal-packages/run-engine/src/engine/index.ts
  • internal-packages/schedule-engine/src/engine/distributedScheduling.ts
  • apps/webapp/app/runEngine/services/batchTrigger.server.ts
  • apps/webapp/app/v3/services/resumeTaskDependency.server.ts
  • apps/webapp/app/v3/commonWorker.server.ts
  • apps/webapp/app/v3/services/cancelDevSessionRuns.server.ts
  • apps/webapp/test/distributedScheduling.test.ts
  • apps/webapp/app/v3/services/retryAttempt.server.ts
  • packages/redis-worker/src/worker.ts
  • apps/webapp/app/v3/services/resumeBatchRun.server.ts
  • internal-packages/schedule-engine/test/scheduleEngine.test.ts
  • apps/webapp/app/v3/services/executeTasksWaitingForDeploy.ts
  • internal-packages/schedule-engine/src/engine/types.ts
  • apps/webapp/app/v3/scheduleEngine.server.ts
  • apps/webapp/app/v3/services/batchTriggerV3.server.ts
  • apps/webapp/app/v3/services/upsertTaskSchedule.server.ts
  • apps/webapp/app/env.server.ts
🧰 Additional context used
🪛 LanguageTool
internal-packages/schedule-engine/README.md

[style] ~51-~51: ‘exactly the same’ might be wordy. Consider a shorter alternative.
Context: ...t all scheduled tasks from executing at exactly the same moment: ```typescript import { calcula...

(EN_WORDINESS_PREMIUM_EXACTLY_THE_SAME)


[uncategorized] ~101-~101: Loose punctuation mark.
Context: ...these configuration options: - prisma: PrismaClient instance - redis: Redis ...

(UNLIKELY_OPENING_PUNCTUATION)

⏰ Context from checks skipped due to timeout of 90000ms (25)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (2, 10)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (7, 10)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (10, 10)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (4, 10)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (8, 10)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (9, 10)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (5, 10)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (6, 10)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (1, 10)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (3, 10)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (8, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (7, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (4, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (6, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (5, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (3, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (1, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (2, 8)
  • GitHub Check: units / packages / 🧪 Unit Tests: Packages (1, 1)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - pnpm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - pnpm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - npm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - npm)
  • GitHub Check: typecheck / typecheck
  • GitHub Check: Analyze (javascript-typescript)

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

🔭 Outside diff range comments (3)
apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.deployments/route.tsx (2)

52-55: Remove the stale deploymentIndexingIsRetryable import

The retry-indexing UI and worker flow were removed, yet the helper is still imported.
Keeping it around adds dead code and a silent dependency that will be forgotten later.

-import { deploymentIndexingIsRetryable } from "~/v3/deploymentStatus";

328-343: canRetryIndexing is now pointless and causes an empty pop-over

canRetryIndexing is still calculated but no longer drives any menu item.
When it is true (and canBeMadeCurrent is false) we render the 3-dot menu with no entries, producing a confusing blank pop-over for users.

Proposed minimal cleanup:

-  const canRetryIndexing = deployment.isLatest && deploymentIndexingIsRetryable(deployment);
   const canBeRolledBack =
     canBeMadeCurrent &&
     currentDeployment?.version &&
     compareDeploymentVersions(deployment.version, currentDeployment.version) === -1;
   const canBePromoted = canBeMadeCurrent && !canBeRolledBack;

-  if (!canBeMadeCurrent && !canRetryIndexing) {
+  if (!canBeMadeCurrent) {
     return (
       <TableCell to={path} isSelected={isSelected}>
         {""}
       </TableCell>
     );
   }

…and delete the now-unused canRetryIndexing computation (together with the import noted above).

This avoids the UX glitch and eliminates redundant logic.

apps/webapp/app/v3/services/cancelTaskRunV1.server.ts (1)

114-121: Enqueue dependency-cancellation jobs in parallel to improve latency.

Inside a tight loop we await each CancelTaskAttemptDependenciesService.enqueue, forcing N sequential round-trips to Redis:

for (const attempt of attempts) {
  await CancelTaskAttemptDependenciesService.enqueue(attempt.id);
}

This can be cut from O(N) network RTTs to ~1 by batching with Promise.all:

-    for (const attempt of attempts) {
-      await CancelTaskAttemptDependenciesService.enqueue(attempt.id);
-    }
+    await Promise.all(
+      attempts.map((a) =>
+        CancelTaskAttemptDependenciesService.enqueue(a.id)
+      ),
+    );

Throughput is higher and the surrounding cancellation flow finishes sooner.

♻️ Duplicate comments (2)
internal-packages/schedule-engine/src/engine/index.ts (2)

616-623: Job-ID collision risk persists – ensure uniqueness

enqueue() still uses only instanceId for the job ID; multiple runs queued before pruning will overwrite each other or be rejected.

-          id: `scheduled-task-instance:${instanceId}`,
+          // Include the exact schedule time to guarantee uniqueness
+          id: `scheduled-task-instance:${instanceId}:${exactScheduleTime.getTime()}`,

352-355: Guard missing for optional dev-environment connectivity handler

isDevEnvironmentConnectedHandler is invoked unconditionally and will throw if the option is omitted.

-          const [devConnectedError, isConnected] = await tryCatch(
-            this.options.isDevEnvironmentConnectedHandler(instance.environment.id)
-          );
+          let isConnected = false;
+          let devConnectedError: unknown;
+          if (this.options.isDevEnvironmentConnectedHandler) {
+            [devConnectedError, isConnected] = await tryCatch(
+              this.options.isDevEnvironmentConnectedHandler(instance.environment.id)
+            );
+          } else {
+            shouldTrigger = false;
+            skipReason = "dev_connection_handler_missing";
+          }
🧹 Nitpick comments (4)
internal-packages/schedule-engine/src/engine/index.ts (3)

130-139: Prefer findUnique over findFirst for primary-key lookups

id is a unique/PK column; findUnique is faster, conveys intent, and avoids accidental surprises if the unique constraint changes.

-        const instance = await this.prisma.taskScheduleInstance.findFirst({
+        const instance = await this.prisma.taskScheduleInstance.findUnique({
           where: { id: params.instanceId },
           include: {
             taskSchedule: true,
             environment: true,
           },
         });

Apply the same change in triggerScheduledTask.

Also applies to: 259-273


159-166: Using new Date() when lastScheduledTimestamp is null can skip earlier executions

If a schedule was created long ago but never run, defaulting to the current time may jump over intended back-dated runs. Consider seeding with the schedule’s creation time or the earliest valid cron match instead.


98-99: Worker logger hard-codes "debug" level

This ignores options.logLevel supplied by the caller and causes inconsistent logging.

-      logger: new Logger("ScheduleEngineWorker", "debug"),
+      logger: new Logger("ScheduleEngineWorker", (this.options.logLevel ?? "info") as any),
apps/webapp/app/v3/commonWorker.server.ts (1)

201-204: Add defensive logging / metrics around email delivery.

sendEmail may throw network-level errors (SMTP, SES throttling, etc.). Letting the exception propagate re-queues the job, but you lose the root-cause context. Wrap with try/catch to add structured logs (or increment a failure metric) before re-throwing:

-      scheduleEmail: async ({ payload }) => {
-        await sendEmail(payload);
-      },
+      scheduleEmail: async ({ payload }) => {
+        try {
+          await sendEmail(payload);
+        } catch (err) {
+          logger.error("scheduleEmail failed", { payload, err });
+          throw err; // preserve retry semantics
+        }
+      },

This makes post-mortems faster without affecting job retries.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 42c3f51 and 7553d8c.

📒 Files selected for processing (14)
  • apps/webapp/app/components/runs/v3/RetryDeploymentIndexingDialog.tsx (0 hunks)
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.deployments/route.tsx (1 hunks)
  • apps/webapp/app/routes/resources.$projectId.deployments.$deploymentShortCode.retry-indexing.ts (0 hunks)
  • apps/webapp/app/services/worker.server.ts (17 hunks)
  • apps/webapp/app/v3/commonWorker.server.ts (3 hunks)
  • apps/webapp/app/v3/scheduleEngine.server.ts (1 hunks)
  • apps/webapp/app/v3/services/cancelTaskAttemptDependencies.server.ts (2 hunks)
  • apps/webapp/app/v3/services/cancelTaskRunV1.server.ts (1 hunks)
  • apps/webapp/app/v3/services/indexDeployment.server.ts (0 hunks)
  • apps/webapp/app/v3/services/resumeTaskRunDependencies.server.ts (0 hunks)
  • apps/webapp/app/v3/services/retryDeploymentIndexing.server.ts (0 hunks)
  • internal-packages/schedule-engine/src/engine/index.ts (1 hunks)
  • internal-packages/schedule-engine/src/engine/types.ts (1 hunks)
  • packages/redis-worker/src/worker.ts (3 hunks)
💤 Files with no reviewable changes (5)
  • apps/webapp/app/components/runs/v3/RetryDeploymentIndexingDialog.tsx
  • apps/webapp/app/routes/resources.$projectId.deployments.$deploymentShortCode.retry-indexing.ts
  • apps/webapp/app/v3/services/retryDeploymentIndexing.server.ts
  • apps/webapp/app/v3/services/resumeTaskRunDependencies.server.ts
  • apps/webapp/app/v3/services/indexDeployment.server.ts
🚧 Files skipped from review as they are similar to previous changes (5)
  • apps/webapp/app/v3/services/cancelTaskAttemptDependencies.server.ts
  • internal-packages/schedule-engine/src/engine/types.ts
  • packages/redis-worker/src/worker.ts
  • apps/webapp/app/services/worker.server.ts
  • apps/webapp/app/v3/scheduleEngine.server.ts
🧰 Additional context used
🧬 Code Graph Analysis (2)
apps/webapp/app/v3/services/cancelTaskRunV1.server.ts (1)
apps/webapp/app/v3/services/cancelTaskAttemptDependencies.server.ts (1)
  • CancelTaskAttemptDependenciesService (7-70)
apps/webapp/app/v3/commonWorker.server.ts (10)
internal-packages/emails/src/index.tsx (1)
  • DeliverEmailSchema (20-32)
apps/webapp/app/services/email.server.ts (1)
  • sendEmail (104-106)
apps/webapp/app/runEngine/services/batchTrigger.server.ts (2)
  • payload (657-687)
  • RunEngineBatchTriggerService (52-688)
apps/webapp/app/v3/services/batchTriggerV3.server.ts (2)
  • payload (902-932)
  • BatchTriggerV3Service (95-933)
apps/webapp/app/v3/services/resumeTaskDependency.server.ts (1)
  • ResumeTaskDependencyService (8-172)
apps/webapp/app/v3/services/timeoutDeployment.server.ts (1)
  • TimeoutDeploymentService (8-70)
apps/webapp/app/v3/services/executeTasksWaitingForDeploy.ts (1)
  • ExecuteTasksWaitingForDeployService (8-117)
apps/webapp/app/v3/services/retryAttempt.server.ts (1)
  • RetryAttemptService (7-36)
apps/webapp/app/v3/services/cancelTaskAttemptDependencies.server.ts (1)
  • CancelTaskAttemptDependenciesService (7-70)
apps/webapp/app/v3/services/cancelDevSessionRuns.server.ts (1)
  • CancelDevSessionRunsService (18-107)
⏰ Context from checks skipped due to timeout of 90000ms (25)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (4, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (7, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (2, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (5, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (8, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (3, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (9, 10)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (6, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (7, 10)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (1, 10)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (3, 10)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (8, 10)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (1, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (10, 10)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (2, 10)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (4, 10)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (6, 10)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (5, 10)
  • GitHub Check: units / packages / 🧪 Unit Tests: Packages (1, 1)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - npm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - npm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - pnpm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - pnpm)
  • GitHub Check: typecheck / typecheck
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (2)
internal-packages/schedule-engine/src/engine/index.ts (1)

230-233: Retry / finalAttempt logic is a stub

finalAttempt is always false; failures inside triggerScheduledTask will bubble and potentially spam retries without back-off. Verify the intended retry semantics and wire them up.

apps/webapp/app/v3/commonWorker.server.ts (1)

191-195: Ensure env numeric values are coerced to numbers.

@trigger.dev/redis-worker expects workers, tasksPerWorker, and limit to be numbers.
If env surfaces raw strings, the worker will silently treat them as NaN, effectively disabling the concurrency limits.

-      workers: env.COMMON_WORKER_CONCURRENCY_WORKERS,
-      tasksPerWorker: env.COMMON_WORKER_CONCURRENCY_TASKS_PER_WORKER,
-      limit: env.COMMON_WORKER_CONCURRENCY_LIMIT,
+      workers: Number(env.COMMON_WORKER_CONCURRENCY_WORKERS),
+      tasksPerWorker: Number(env.COMMON_WORKER_CONCURRENCY_TASKS_PER_WORKER),
+      limit: Number(env.COMMON_WORKER_CONCURRENCY_LIMIT),

Confirm that the env helper already returns numbers; otherwise, coerce explicitly as above.

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

♻️ Duplicate comments (2)
internal-packages/schedule-engine/src/engine/index.ts (2)

352-356: Guard optional isDevEnvironmentConnectedHandler before invoking

this.options.isDevEnvironmentConnectedHandler is still called unconditionally. If the option isn’t supplied, this throws TypeError: undefined is not a function, breaking triggers in development environments.
Add a presence check or make the handler mandatory.


616-622: Job-ID collision risk remains

id: \scheduled-task-instance:${instanceId}`is reused for every run. If a previous run hasn’t been pruned,enqueue` may reject or overwrite, silently dropping executions.

- id: `scheduled-task-instance:${instanceId}`,
+ id: `scheduled-task-instance:${instanceId}:${exactScheduleTime.getTime()}`,
🧹 Nitpick comments (1)
internal-packages/schedule-engine/src/engine/index.ts (1)

348-350: High-cardinality metric label

dev_environment_checks_total tags every sample with environment_id, which can explode the cardinality of your time-series database.
Consider using low-cardinality labels (e.g. environment_type) and exposing high-cardinality data via logs instead.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 28d8030 and 8ff6af5.

📒 Files selected for processing (1)
  • internal-packages/schedule-engine/src/engine/index.ts (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (25)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (7, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (4, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (6, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (3, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (8, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (5, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (9, 10)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (10, 10)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (1, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (7, 10)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (6, 10)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (2, 10)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (8, 10)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (3, 10)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (2, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (1, 10)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (5, 10)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (4, 10)
  • GitHub Check: units / packages / 🧪 Unit Tests: Packages (1, 1)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - npm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - pnpm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - npm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - pnpm)
  • GitHub Check: typecheck / typecheck
  • GitHub Check: Analyze (javascript-typescript)

@ericallam ericallam merged commit ea6f66b into main Jun 17, 2025
33 checks passed
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.

2 participants