Skip to content

re2: Queue indexing, queue trigger changes #1808

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 22 commits into from
Mar 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
7a58439
WIP queue indexing
ericallam Mar 20, 2025
7e411ac
New PENDING_VERSION system which now requires queues to exist at dequ…
ericallam Mar 20, 2025
1bec4e1
Getting the queues indexing to work by passing them to the create bac…
ericallam Mar 20, 2025
941e03b
Using the new PENDING_VERSION status now in the UI
ericallam Mar 20, 2025
cbe651e
Fix useTaskTrigger queue option params and remove exportName from e2e…
ericallam Mar 21, 2025
02eeefd
Increase maxRetriesPerRequest in CI
ericallam Mar 21, 2025
f4a1eb1
Fixed changesets and added one
ericallam Mar 21, 2025
bee5e75
Fixed cli e2e tests
ericallam Mar 21, 2025
de5e0c8
try to fix flaky tests
ericallam Mar 21, 2025
f58dee1
Fix the task run status reason UI
ericallam Mar 21, 2025
8d514b9
Use orderableName on the TaskQueue and add the releaseConcurrencyOnWa…
ericallam Mar 21, 2025
ad08756
Run tests sequentially in CI, and pass "--run" to vitest to disable w…
ericallam Mar 21, 2025
e53eed1
Fixed the types on pauseQueue service
ericallam Mar 21, 2025
233a22d
Move runs sidebar menu item below tasks and alerts into the manage se…
ericallam Mar 21, 2025
c87ff2c
Various fixes for no longer having the exportName
ericallam Mar 21, 2025
b65f225
Tasks are indexed even if you don't export them 🤩
ericallam Mar 21, 2025
109bfac
Remove exportName from the trigger span names
ericallam Mar 21, 2025
671ff26
Removing more exportName stuff
ericallam Mar 21, 2025
5a72567
Fix the unit tests CI action
ericallam Mar 21, 2025
f46a409
Fixed typescript error
ericallam Mar 21, 2025
b72b7c2
Fixed typechecks
ericallam Mar 21, 2025
f1d5886
Another attempt at getting CI to pass tests
ericallam Mar 21, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .changeset/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,13 @@
"access": "public",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": ["webapp", "supervisor", "coordinator", "docker-provider", "kubernetes-provider"],
"ignore": [
"webapp",
"coordinator",
"docker-provider",
"kubernetes-provider",
"supervisor"
],
"___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH": {
"onlyUpdatePeerDependentsWhenOutOfRange": true
}
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/unit-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:
run: pnpm run generate

- name: 🧪 Run Webapp Unit Tests
run: pnpm run test --filter webapp
run: pnpm run test:webapp
env:
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/postgres
DIRECT_URL: postgresql://postgres:postgres@localhost:5432/postgres
Expand All @@ -47,7 +47,7 @@ jobs:
ENCRYPTION_KEY: "secret"

- name: 🧪 Run Package Unit Tests
run: pnpm run test --filter "@trigger.dev/*"
run: pnpm run test:packages

- name: 🧪 Run Internal Unit Tests
run: pnpm run test --filter "@internal/*"
run: pnpm run test:internal
29 changes: 13 additions & 16 deletions apps/webapp/app/components/navigation/SideMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,12 @@ export function SideMenu({
to={v3EnvironmentPath(organization, project, environment)}
data-action="tasks"
/>
<SideMenuItem
name="Runs"
icon={RunsIcon}
activeIconColor="text-teal-500"
to={v3RunsPath(organization, project, environment)}
/>
<SideMenuItem
name="Batches"
icon={Squares2X2Icon}
Expand Down Expand Up @@ -212,22 +218,6 @@ export function SideMenu({
/>
</div>

<SideMenuSection title="Observability">
<SideMenuItem
name="Runs"
icon={RunsIcon}
activeIconColor="text-teal-500"
to={v3RunsPath(organization, project, environment)}
/>
<SideMenuItem
name="Alerts"
icon={BellAlertIcon}
activeIconColor="text-red-500"
to={v3ProjectAlertsPath(organization, project, environment)}
data-action="alerts"
/>
</SideMenuSection>

<SideMenuSection title="Manage">
<SideMenuItem
name="API keys"
Expand All @@ -243,6 +233,13 @@ export function SideMenu({
to={v3EnvironmentVariablesPath(organization, project, environment)}
data-action="environment variables"
/>
<SideMenuItem
name="Alerts"
icon={BellAlertIcon}
activeIconColor="text-red-500"
to={v3ProjectAlertsPath(organization, project, environment)}
data-action="alerts"
/>
<SideMenuItem
name="Project settings"
icon={Cog8ToothIcon}
Expand Down
7 changes: 6 additions & 1 deletion apps/webapp/app/components/primitives/Table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,12 @@ export const TableHeaderCell = forwardRef<HTMLTableCellElement, TableHeaderCellP
{hiddenLabel ? (
<span className="sr-only">{children}</span>
) : tooltip ? (
<div className="flex items-center gap-1">
<div
className={cn("flex items-center gap-1", {
"justify-center": alignment === "center",
"justify-end": alignment === "right",
})}
>
{children}
<InfoIconTooltip content={tooltip} contentClassName="normal-case tracking-normal" />
</div>
Expand Down
8 changes: 4 additions & 4 deletions apps/webapp/app/components/runs/v3/TaskPath.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,16 @@ export function TaskPath({ filePath, functionName, className }: TaskPathProps) {
);
}

type TaskFunctionNameProps = {
functionName: string;
type TaskFileNameProps = {
fileName: string;
variant?: InlineCodeVariant;
className?: string;
};

export function TaskFunctionName({ variant, functionName, className }: TaskFunctionNameProps) {
export function TaskFileName({ variant, fileName, className }: TaskFileNameProps) {
return (
<InlineCode variant={variant} className={cn("text-text-dimmed", className)}>
{`${functionName}()`}
{`${fileName}`}
</InlineCode>
);
}
50 changes: 47 additions & 3 deletions apps/webapp/app/components/runs/v3/TaskRunStatus.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@ import { type TaskRunStatus } from "@trigger.dev/database";
import assertNever from "assert-never";
import { HourglassIcon } from "lucide-react";
import { TimedOutIcon } from "~/assets/icons/TimedOutIcon";
import { Callout } from "~/components/primitives/Callout";
import { Spinner } from "~/components/primitives/Spinner";
import { cn } from "~/utils/cn";

export const allTaskRunStatuses = [
"DELAYED",
"WAITING_FOR_DEPLOY",
"PENDING_VERSION",
"PENDING",
"EXECUTING",
"RETRYING_AFTER_FAILURE",
Expand All @@ -37,7 +39,7 @@ export const allTaskRunStatuses = [
] as const satisfies Readonly<Array<TaskRunStatus>>;

export const filterableTaskRunStatuses = [
"WAITING_FOR_DEPLOY",
"PENDING_VERSION",
"DELAYED",
"PENDING",
"WAITING_TO_RESUME",
Expand All @@ -56,7 +58,8 @@ export const filterableTaskRunStatuses = [
const taskRunStatusDescriptions: Record<TaskRunStatus, string> = {
DELAYED: "Task has been delayed and is waiting to be executed.",
PENDING: "Task is waiting to be executed.",
WAITING_FOR_DEPLOY: "Task needs to be deployed first to start executing.",
PENDING_VERSION: "Run cannot execute until a version includes the task and queue.",
WAITING_FOR_DEPLOY: "Run cannot execute until a version includes the task and queue.",
EXECUTING: "Task is currently being executed.",
RETRYING_AFTER_FAILURE: "Task is being reattempted after a failure.",
WAITING_TO_RESUME: `You have used a "wait" function. When the wait is complete, the task will resume execution.`,
Expand All @@ -73,6 +76,7 @@ const taskRunStatusDescriptions: Record<TaskRunStatus, string> = {

export const QUEUED_STATUSES = [
"PENDING",
"PENDING_VERSION",
"WAITING_FOR_DEPLOY",
"DELAYED",
] satisfies TaskRunStatus[];
Expand Down Expand Up @@ -104,6 +108,43 @@ export function TaskRunStatusCombo({
);
}

const statusReasonsToDescription: Record<string, string> = {
NO_DEPLOYMENT: "No deployment or deployment image reference found for deployed run",
NO_WORKER: "No worker found for run",
TASK_NEVER_REGISTERED: "Task never registered",
QUEUE_NOT_FOUND: "Queue not found",
TASK_NOT_IN_LATEST: "Task not in latest version",
BACKGROUND_WORKER_MISMATCH: "Background worker mismatch",
};

export function TaskRunStatusReason({
status,
statusReason,
}: {
status: TaskRunStatus;
statusReason?: string;
}) {
if (status !== "PENDING_VERSION") {
return null;
}

if (!statusReason) {
return null;
}

const description = statusReasonsToDescription[statusReason];

if (!description) {
return null;
}

return (
<Callout to="https://trigger.dev/docs" variant="warning" className="text-sm">
{description}
</Callout>
);
}

export function TaskRunStatusLabel({ status }: { status: TaskRunStatus }) {
return <span className={runStatusClassNameColor(status)}>{runStatusTitle(status)}</span>;
}
Expand All @@ -120,6 +161,7 @@ export function TaskRunStatusIcon({
return <ClockIcon className={cn(runStatusClassNameColor(status), className)} />;
case "PENDING":
return <RectangleStackIcon className={cn(runStatusClassNameColor(status), className)} />;
case "PENDING_VERSION":
case "WAITING_FOR_DEPLOY":
return <RectangleStackIcon className={cn(runStatusClassNameColor(status), className)} />;
case "EXECUTING":
Expand Down Expand Up @@ -158,6 +200,7 @@ export function runStatusClassNameColor(status: TaskRunStatus): string {
case "PENDING":
case "DELAYED":
return "text-charcoal-500";
case "PENDING_VERSION":
case "WAITING_FOR_DEPLOY":
return "text-amber-500";
case "EXECUTING":
Expand Down Expand Up @@ -194,8 +237,9 @@ export function runStatusTitle(status: TaskRunStatus): string {
return "Delayed";
case "PENDING":
return "Queued";
case "PENDING_VERSION":
case "WAITING_FOR_DEPLOY":
return "Waiting for deploy";
return "Pending version";
case "EXECUTING":
return "Executing";
case "WAITING_TO_RESUME":
Expand Down
4 changes: 3 additions & 1 deletion apps/webapp/app/components/runs/v3/TaskRunsTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,9 @@ export function TaskRunsTable({
<TableCell to={path} className="w-[1%]" actionClassName="pr-0 tabular-nums">
<div className="flex items-center gap-1">
<RectangleStackIcon className="size-4 text-text-dimmed" />
{run.startedAt ? (
{run.isPending ? (
"–"
) : run.startedAt ? (
formatDuration(new Date(run.createdAt), new Date(run.startedAt), {
style: "short",
})
Expand Down
1 change: 1 addition & 0 deletions apps/webapp/app/database-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export const TaskRunAttemptStatus = {

export const TaskRunStatus = {
PENDING: "PENDING",
PENDING_VERSION: "PENDING_VERSION",
WAITING_FOR_DEPLOY: "WAITING_FOR_DEPLOY",
EXECUTING: "EXECUTING",
WAITING_TO_RESUME: "WAITING_TO_RESUME",
Expand Down
5 changes: 0 additions & 5 deletions apps/webapp/app/hooks/useFilterTasks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ type Task = {
id: string;
friendlyId: string;
taskIdentifier: string;
exportName: string;
filePath: string;
triggerSource: string;
};
Expand All @@ -17,10 +16,6 @@ export function useFilterTasks<T extends Task>({ tasks }: { tasks: T[] }) {
return true;
}

if (task.exportName.toLowerCase().includes(text.toLowerCase())) {
return true;
}

if (task.filePath.toLowerCase().includes(text.toLowerCase())) {
return true;
}
Expand Down
2 changes: 1 addition & 1 deletion apps/webapp/app/models/runtimeEnvironment.server.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { AuthenticatedEnvironment } from "@internal/testcontainers";
import type { AuthenticatedEnvironment } from "@internal/run-engine";
import type { Prisma, PrismaClientOrTransaction, RuntimeEnvironment } from "@trigger.dev/database";
import { prisma } from "~/db.server";
import { getUsername } from "~/utils/username";
Expand Down
4 changes: 2 additions & 2 deletions apps/webapp/app/models/taskQueue.server.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { QueueOptions } from "@trigger.dev/core/v3/schemas";
import { QueueManifest } from "@trigger.dev/core/v3/schemas";
import { TaskQueue } from "@trigger.dev/database";
import { prisma } from "~/db.server";

Expand Down Expand Up @@ -35,7 +35,7 @@ export async function findQueueInEnvironment(
return;
}

const queueConfig = QueueOptions.safeParse(task.queueConfig);
const queueConfig = QueueManifest.safeParse(task.queueConfig);

if (queueConfig.success) {
const taskQueueName = queueConfig.data.name
Expand Down
1 change: 1 addition & 0 deletions apps/webapp/app/models/taskRun.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ export function batchTaskRunItemStatusForRunStatus(
case TaskRunStatus.TIMED_OUT:
return BatchTaskRunItemStatus.FAILED;
case TaskRunStatus.PENDING:
case TaskRunStatus.PENDING_VERSION:
case TaskRunStatus.WAITING_FOR_DEPLOY:
case TaskRunStatus.WAITING_TO_RESUME:
case TaskRunStatus.RETRYING_AFTER_FAILURE:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,9 @@ export class ApiRetrieveRunPresenter extends BasePresenter {
case "DELAYED": {
return "DELAYED";
}
case "PENDING_VERSION": {
return "PENDING_VERSION";
}
case "WAITING_FOR_DEPLOY": {
return "WAITING_FOR_DEPLOY";
}
Expand Down Expand Up @@ -257,7 +260,11 @@ export class ApiRetrieveRunPresenter extends BasePresenter {
}

static apiBooleanHelpersFromRunStatus(status: RunStatus) {
const isQueued = status === "QUEUED" || status === "WAITING_FOR_DEPLOY" || status === "DELAYED";
const isQueued =
status === "QUEUED" ||
status === "WAITING_FOR_DEPLOY" ||
status === "DELAYED" ||
status === "PENDING_VERSION";
const isExecuting = status === "EXECUTING" || status === "REATTEMPTING" || status === "FROZEN";
const isCompleted =
status === "COMPLETED" ||
Expand Down
3 changes: 3 additions & 0 deletions apps/webapp/app/presenters/v3/ApiRunListPresenter.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,9 @@ export class ApiRunListPresenter extends BasePresenter {
switch (status) {
case "DELAYED":
return "DELAYED";
case "PENDING_VERSION": {
return "PENDING_VERSION";
}
case "WAITING_FOR_DEPLOY": {
return "WAITING_FOR_DEPLOY";
}
Expand Down
3 changes: 1 addition & 2 deletions apps/webapp/app/presenters/v3/DeploymentPresenter.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,11 +108,10 @@ export class DeploymentPresenter {
tasks: {
select: {
slug: true,
exportName: true,
filePath: true,
},
orderBy: {
exportName: "asc",
slug: "asc",
},
},
sdkVersion: true,
Expand Down
6 changes: 5 additions & 1 deletion apps/webapp/app/presenters/v3/QueueListPresenter.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,16 +56,19 @@ export class QueueListPresenter extends BasePresenter {
const queues = await this._replica.taskQueue.findMany({
where: {
runtimeEnvironmentId: environment.id,
version: "V2",
},
select: {
friendlyId: true,
name: true,
orderableName: true,
concurrencyLimit: true,
type: true,
paused: true,
releaseConcurrencyOnWaitpoint: true,
},
orderBy: {
name: "asc",
orderableName: "asc",
},
skip: (page - 1) * this.perPage,
take: this.perPage,
Expand All @@ -92,6 +95,7 @@ export class QueueListPresenter extends BasePresenter {
queued: results[0][queue.name] ?? 0,
concurrencyLimit: queue.concurrencyLimit ?? null,
paused: queue.paused,
releaseConcurrencyOnWaitpoint: queue.releaseConcurrencyOnWaitpoint,
})
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ export class QueueRetrievePresenter extends BasePresenter {
queued: results[0]?.[queue.name] ?? 0,
concurrencyLimit: queue.concurrencyLimit ?? null,
paused: queue.paused,
releaseConcurrencyOnWaitpoint: queue.releaseConcurrencyOnWaitpoint,
}),
};
}
Expand Down Expand Up @@ -105,6 +106,7 @@ export function toQueueItem(data: {
queued: number;
concurrencyLimit: number | null;
paused: boolean;
releaseConcurrencyOnWaitpoint: boolean;
}): QueueItem {
return {
id: data.friendlyId,
Expand All @@ -115,5 +117,6 @@ export function toQueueItem(data: {
queued: data.queued,
concurrencyLimit: data.concurrencyLimit,
paused: data.paused,
releaseConcurrencyOnWaitpoint: data.releaseConcurrencyOnWaitpoint,
};
}
Loading