Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3069ebf0d8 | |||
| e133e628ca | |||
| 098932ea96 | |||
| 65f960e883 | |||
| ccbeff47e6 | |||
| 7c8f2df105 | |||
| fd44dabfe0 | |||
| 5daed3f69d | |||
| 596bf78e55 | |||
| 6ca66b76f4 | |||
| 29ef0395ce | |||
| 55d1f8c677 | |||
| 9835f4ec55 | |||
| 7fae10db23 | |||
| 8cf1f0a37d | |||
| dba4313c5c | |||
| 506613dc92 |
@@ -115,14 +115,17 @@
|
||||
"sharp-emus-compare",
|
||||
"sharp-zebras-serve",
|
||||
"shiny-coats-cry",
|
||||
"silly-buses-obey",
|
||||
"silly-suits-switch",
|
||||
"silver-doors-juggle",
|
||||
"six-ligers-exist",
|
||||
"sixty-insects-watch",
|
||||
"slow-buses-own",
|
||||
"slow-kiwis-hide",
|
||||
"slow-sloths-retire",
|
||||
"smart-needles-move",
|
||||
"smart-olives-eat",
|
||||
"sour-pugs-teach",
|
||||
"spicy-lamps-smoke",
|
||||
"spicy-terms-bow",
|
||||
"strange-ghosts-matter",
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@trigger.dev/core": patch
|
||||
---
|
||||
|
||||
Add callback to checkpoint created message
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
"@trigger.dev/core": patch
|
||||
---
|
||||
|
||||
v3: vercel edge runtime support
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
"@trigger.dev/core": patch
|
||||
---
|
||||
|
||||
v3: fix otel flushing causing CLEANUP ack timeout errors by always setting a forceFlushTimeoutMillis value
|
||||
@@ -1162,13 +1162,7 @@ class TaskCoordinator {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!checkpoint.docker || !willSimulate) {
|
||||
socket.emit("REQUEST_EXIT", {
|
||||
version: "v1",
|
||||
});
|
||||
}
|
||||
|
||||
this.#platformSocket?.send("CHECKPOINT_CREATED", {
|
||||
const ack = await this.#platformSocket?.sendWithAck("CHECKPOINT_CREATED", {
|
||||
version: "v1",
|
||||
attemptFriendlyId: message.attemptFriendlyId,
|
||||
docker: checkpoint.docker,
|
||||
@@ -1179,6 +1173,17 @@ class TaskCoordinator {
|
||||
now: message.now,
|
||||
},
|
||||
});
|
||||
|
||||
if (ack?.keepRunAlive) {
|
||||
logger.log("keeping run alive after duration checkpoint", { runId: socket.data.runId });
|
||||
return;
|
||||
}
|
||||
|
||||
if (!checkpoint.docker || !willSimulate) {
|
||||
socket.emit("REQUEST_EXIT", {
|
||||
version: "v1",
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
socket.on("WAIT_FOR_TASK", async (message, callback) => {
|
||||
@@ -1205,13 +1210,7 @@ class TaskCoordinator {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!checkpoint.docker || !willSimulate) {
|
||||
socket.emit("REQUEST_EXIT", {
|
||||
version: "v1",
|
||||
});
|
||||
}
|
||||
|
||||
this.#platformSocket?.send("CHECKPOINT_CREATED", {
|
||||
const ack = await this.#platformSocket?.sendWithAck("CHECKPOINT_CREATED", {
|
||||
version: "v1",
|
||||
attemptFriendlyId: message.attemptFriendlyId,
|
||||
docker: checkpoint.docker,
|
||||
@@ -1221,6 +1220,17 @@ class TaskCoordinator {
|
||||
friendlyId: message.friendlyId,
|
||||
},
|
||||
});
|
||||
|
||||
if (ack?.keepRunAlive) {
|
||||
logger.log("keeping run alive after task checkpoint", { runId: socket.data.runId });
|
||||
return;
|
||||
}
|
||||
|
||||
if (!checkpoint.docker || !willSimulate) {
|
||||
socket.emit("REQUEST_EXIT", {
|
||||
version: "v1",
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
socket.on("WAIT_FOR_BATCH", async (message, callback) => {
|
||||
@@ -1247,13 +1257,7 @@ class TaskCoordinator {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!checkpoint.docker || !willSimulate) {
|
||||
socket.emit("REQUEST_EXIT", {
|
||||
version: "v1",
|
||||
});
|
||||
}
|
||||
|
||||
this.#platformSocket?.send("CHECKPOINT_CREATED", {
|
||||
const ack = await this.#platformSocket?.sendWithAck("CHECKPOINT_CREATED", {
|
||||
version: "v1",
|
||||
attemptFriendlyId: message.attemptFriendlyId,
|
||||
docker: checkpoint.docker,
|
||||
@@ -1264,6 +1268,17 @@ class TaskCoordinator {
|
||||
runFriendlyIds: message.runFriendlyIds,
|
||||
},
|
||||
});
|
||||
|
||||
if (ack?.keepRunAlive) {
|
||||
logger.log("keeping run alive after batch checkpoint", { runId: socket.data.runId });
|
||||
return;
|
||||
}
|
||||
|
||||
if (!checkpoint.docker || !willSimulate) {
|
||||
socket.emit("REQUEST_EXIT", {
|
||||
version: "v1",
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
socket.on("INDEX_TASKS", async (message, callback) => {
|
||||
|
||||
@@ -528,7 +528,7 @@ export type Tree<TData> = {
|
||||
/** A tree but flattened so it can easily be used for DOM elements */
|
||||
export type FlatTreeItem<TData> = {
|
||||
id: string;
|
||||
parentId: string | undefined;
|
||||
parentId?: string | undefined;
|
||||
children: string[];
|
||||
hasChildren: boolean;
|
||||
/** The indentation level, the root is 0 */
|
||||
|
||||
@@ -186,3 +186,9 @@ export { apiRateLimiter } from "./services/apiRateLimit.server";
|
||||
export { socketIo } from "./v3/handleSocketIo.server";
|
||||
export { wss } from "./v3/handleWebsockets.server";
|
||||
export { registryProxy } from "./v3/registryProxy.server";
|
||||
import { eventLoopMonitor } from "./eventLoopMonitor.server";
|
||||
import { env } from "./env.server";
|
||||
|
||||
if (env.EVENT_LOOP_MONITOR_ENABLED === "1") {
|
||||
eventLoopMonitor.enable();
|
||||
}
|
||||
|
||||
@@ -204,6 +204,8 @@ const EnvironmentSchema = z.object({
|
||||
|
||||
USAGE_OPEN_METER_API_KEY: z.string().optional(),
|
||||
USAGE_OPEN_METER_BASE_URL: z.string().optional(),
|
||||
EVENT_LOOP_MONITOR_ENABLED: z.string().default("1"),
|
||||
MAXIMUM_LIVE_RELOADING_EVENTS: z.coerce.number().int().default(1000),
|
||||
});
|
||||
|
||||
export type Environment = z.infer<typeof EnvironmentSchema>;
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
import { createHook } from "node:async_hooks";
|
||||
import { singleton } from "./utils/singleton";
|
||||
import { tracer } from "./v3/tracer.server";
|
||||
|
||||
const THRESHOLD_NS = 1e8; // 100ms
|
||||
|
||||
const cache = new Map<number, { type: string; start?: [number, number] }>();
|
||||
|
||||
function init(asyncId: number, type: string, triggerAsyncId: number, resource: any) {
|
||||
cache.set(asyncId, {
|
||||
type,
|
||||
});
|
||||
}
|
||||
|
||||
function destroy(asyncId: number) {
|
||||
cache.delete(asyncId);
|
||||
}
|
||||
|
||||
function before(asyncId: number) {
|
||||
const cached = cache.get(asyncId);
|
||||
|
||||
if (!cached) {
|
||||
return;
|
||||
}
|
||||
|
||||
cache.set(asyncId, {
|
||||
...cached,
|
||||
start: process.hrtime(),
|
||||
});
|
||||
}
|
||||
|
||||
function after(asyncId: number) {
|
||||
const cached = cache.get(asyncId);
|
||||
|
||||
if (!cached) {
|
||||
return;
|
||||
}
|
||||
|
||||
cache.delete(asyncId);
|
||||
|
||||
if (!cached.start) {
|
||||
return;
|
||||
}
|
||||
|
||||
const diff = process.hrtime(cached.start);
|
||||
const diffNs = diff[0] * 1e9 + diff[1];
|
||||
if (diffNs > THRESHOLD_NS) {
|
||||
const time = diffNs / 1e6; // in ms
|
||||
|
||||
const newSpan = tracer.startSpan("event-loop-blocked", {
|
||||
startTime: new Date(new Date().getTime() - time),
|
||||
attributes: {
|
||||
asyncType: cached.type,
|
||||
label: "EventLoopMonitor",
|
||||
},
|
||||
});
|
||||
|
||||
newSpan.end();
|
||||
}
|
||||
}
|
||||
|
||||
export const eventLoopMonitor = singleton("eventLoopMonitor", () => {
|
||||
const hook = createHook({ init, before, after, destroy });
|
||||
|
||||
return {
|
||||
enable: () => {
|
||||
console.log("🥸 Initializing event loop monitor");
|
||||
|
||||
hook.enable();
|
||||
},
|
||||
disable: () => {
|
||||
console.log("🥸 Disabling event loop monitor");
|
||||
|
||||
hook.disable();
|
||||
},
|
||||
};
|
||||
});
|
||||
@@ -26,7 +26,7 @@ export function useEventSource(
|
||||
const eventSource = new EventSource(url, init);
|
||||
eventSource.addEventListener(event ?? "message", handler);
|
||||
|
||||
// rest data if dependencies change
|
||||
// reset data if dependencies change
|
||||
setData(null);
|
||||
|
||||
function handler(event: MessageEvent) {
|
||||
|
||||
@@ -65,59 +65,55 @@ export async function findEnvironmentById(id: string) {
|
||||
}
|
||||
|
||||
export async function createNewSession(environment: RuntimeEnvironment, ipAddress: string) {
|
||||
return prisma.$transaction(async (tx) => {
|
||||
const session = await tx.runtimeEnvironmentSession.create({
|
||||
data: {
|
||||
environmentId: environment.id,
|
||||
ipAddress,
|
||||
},
|
||||
});
|
||||
|
||||
await tx.runtimeEnvironment.update({
|
||||
where: {
|
||||
id: environment.id,
|
||||
},
|
||||
data: {
|
||||
currentSessionId: session.id,
|
||||
},
|
||||
});
|
||||
|
||||
return session;
|
||||
const session = await prisma.runtimeEnvironmentSession.create({
|
||||
data: {
|
||||
environmentId: environment.id,
|
||||
ipAddress,
|
||||
},
|
||||
});
|
||||
|
||||
await prisma.runtimeEnvironment.update({
|
||||
where: {
|
||||
id: environment.id,
|
||||
},
|
||||
data: {
|
||||
currentSessionId: session.id,
|
||||
},
|
||||
});
|
||||
|
||||
return session;
|
||||
}
|
||||
|
||||
export async function disconnectSession(environmentId: string) {
|
||||
return prisma.$transaction(async (tx) => {
|
||||
const environment = await tx.runtimeEnvironment.findUnique({
|
||||
where: {
|
||||
id: environmentId,
|
||||
},
|
||||
});
|
||||
|
||||
if (!environment || !environment.currentSessionId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const session = await tx.runtimeEnvironmentSession.update({
|
||||
where: {
|
||||
id: environment.currentSessionId,
|
||||
},
|
||||
data: {
|
||||
disconnectedAt: new Date(),
|
||||
},
|
||||
});
|
||||
|
||||
await tx.runtimeEnvironment.update({
|
||||
where: {
|
||||
id: environment.id,
|
||||
},
|
||||
data: {
|
||||
currentSessionId: null,
|
||||
},
|
||||
});
|
||||
|
||||
return session;
|
||||
const environment = await prisma.runtimeEnvironment.findUnique({
|
||||
where: {
|
||||
id: environmentId,
|
||||
},
|
||||
});
|
||||
|
||||
if (!environment || !environment.currentSessionId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const session = await prisma.runtimeEnvironmentSession.update({
|
||||
where: {
|
||||
id: environment.currentSessionId,
|
||||
},
|
||||
data: {
|
||||
disconnectedAt: new Date(),
|
||||
},
|
||||
});
|
||||
|
||||
await prisma.runtimeEnvironment.update({
|
||||
where: {
|
||||
id: environment.id,
|
||||
},
|
||||
data: {
|
||||
currentSessionId: null,
|
||||
},
|
||||
});
|
||||
|
||||
return session;
|
||||
}
|
||||
|
||||
type DisplayableInputEnvironment = Prisma.RuntimeEnvironmentGetPayload<{
|
||||
|
||||
@@ -4,8 +4,8 @@ import { Direction } from "~/components/runs/RunStatuses";
|
||||
import { FINISHED_STATUSES } from "~/components/runs/v3/TaskRunStatus";
|
||||
import { sqlDatabaseSchema } from "~/db.server";
|
||||
import { displayableEnvironment } from "~/models/runtimeEnvironment.server";
|
||||
import { CANCELLABLE_STATUSES } from "~/v3/services/cancelTaskRun.server";
|
||||
import { BasePresenter } from "./basePresenter.server";
|
||||
import { isCancellableRunStatus } from "~/v3/taskStatus";
|
||||
|
||||
export type RunListOptions = {
|
||||
userId?: string;
|
||||
@@ -291,7 +291,7 @@ export class RunListPresenter extends BasePresenter {
|
||||
taskIdentifier: run.taskIdentifier,
|
||||
spanId: run.spanId,
|
||||
isReplayable: true,
|
||||
isCancellable: CANCELLABLE_STATUSES.includes(run.status),
|
||||
isCancellable: isCancellableRunStatus(run.status),
|
||||
environment: displayableEnvironment(environment, userId),
|
||||
idempotencyKey: run.idempotencyKey ? run.idempotencyKey : undefined,
|
||||
};
|
||||
|
||||
@@ -94,17 +94,24 @@ export class RunStreamPresenter {
|
||||
|
||||
eventEmitter.removeAllListeners();
|
||||
|
||||
unsubscribe().catch((error) => {
|
||||
logger.error("RunStreamPresenter.abort.unsubscribe", {
|
||||
runFriendlyId,
|
||||
traceId: run.traceId,
|
||||
error: {
|
||||
name: error.name,
|
||||
message: error.message,
|
||||
stack: error.stack,
|
||||
},
|
||||
unsubscribe()
|
||||
.then(() => {
|
||||
logger.info("RunStreamPresenter.abort.unsubscribe succeeded", {
|
||||
runFriendlyId,
|
||||
traceId: run.traceId,
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
logger.error("RunStreamPresenter.abort.unsubscribe failed", {
|
||||
runFriendlyId,
|
||||
traceId: run.traceId,
|
||||
error: {
|
||||
name: error.name,
|
||||
message: error.message,
|
||||
stack: error.stack,
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
+66
-23
@@ -1,12 +1,13 @@
|
||||
import {
|
||||
BoltSlashIcon,
|
||||
ChevronDownIcon,
|
||||
ChevronRightIcon,
|
||||
MagnifyingGlassMinusIcon,
|
||||
MagnifyingGlassPlusIcon,
|
||||
} from "@heroicons/react/20/solid";
|
||||
import type { Location } from "@remix-run/react";
|
||||
import { useParams, useRevalidator } from "@remix-run/react";
|
||||
import { LoaderFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { useLoaderData, useParams, useRevalidator } from "@remix-run/react";
|
||||
import { LoaderFunctionArgs, SerializeFrom } from "@remix-run/server-runtime";
|
||||
import { Virtualizer } from "@tanstack/react-virtual";
|
||||
import {
|
||||
formatDurationMilliseconds,
|
||||
@@ -17,10 +18,10 @@ import { RuntimeEnvironmentType } from "@trigger.dev/database";
|
||||
import { motion } from "framer-motion";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import { useHotkeys } from "react-hotkeys-hook";
|
||||
import { typedjson, useTypedLoaderData } from "remix-typedjson";
|
||||
import { ShowParentIcon, ShowParentIconSelected } from "~/assets/icons/ShowParentIcon";
|
||||
import tileBgPath from "~/assets/images/error-banner-tile@2x.png";
|
||||
import { BlankstateInstructions } from "~/components/BlankstateInstructions";
|
||||
import { AdminDebugTooltip } from "~/components/admin/debugTooltip";
|
||||
import { InlineCode } from "~/components/code/InlineCode";
|
||||
import { EnvironmentLabel } from "~/components/environments/EnvironmentLabel";
|
||||
import { MainCenteredContainer, PageBody } from "~/components/layout/AppLayout";
|
||||
@@ -32,6 +33,7 @@ import { Input } from "~/components/primitives/Input";
|
||||
import { NavBar, PageAccessories, PageTitle } from "~/components/primitives/PageHeader";
|
||||
import { Paragraph } from "~/components/primitives/Paragraph";
|
||||
import { Popover, PopoverArrowTrigger, PopoverContent } from "~/components/primitives/Popover";
|
||||
import { Property, PropertyTable } from "~/components/primitives/PropertyTable";
|
||||
import {
|
||||
ResizableHandle,
|
||||
ResizablePanel,
|
||||
@@ -54,7 +56,7 @@ import { useProject } from "~/hooks/useProject";
|
||||
import { useReplaceLocation } from "~/hooks/useReplaceLocation";
|
||||
import { Shortcut, useShortcutKeys } from "~/hooks/useShortcutKeys";
|
||||
import { useUser } from "~/hooks/useUser";
|
||||
import { RunEvent, RunPresenter } from "~/presenters/v3/RunPresenter.server";
|
||||
import { RunPresenter } from "~/presenters/v3/RunPresenter.server";
|
||||
import { getResizableRunSettings, setResizableRunSettings } from "~/services/resizablePanel";
|
||||
import { requireUserId } from "~/services/session.server";
|
||||
import { cn } from "~/utils/cn";
|
||||
@@ -67,8 +69,10 @@ import {
|
||||
v3RunsPath,
|
||||
} from "~/utils/pathBuilder";
|
||||
import { SpanView } from "../resources.orgs.$organizationSlug.projects.v3.$projectParam.runs.$runParam.spans.$spanParam/route";
|
||||
import { AdminDebugTooltip } from "~/components/admin/debugTooltip";
|
||||
import { Property, PropertyTable } from "~/components/primitives/PropertyTable";
|
||||
import { SimpleTooltip } from "~/components/primitives/Tooltip";
|
||||
import { env } from "~/env.server";
|
||||
|
||||
type TraceEvent = NonNullable<SerializeFrom<typeof loader>["trace"]>["events"][0];
|
||||
|
||||
export const loader = async ({ request, params }: LoaderFunctionArgs) => {
|
||||
const userId = await requireUserId(request);
|
||||
@@ -85,10 +89,12 @@ export const loader = async ({ request, params }: LoaderFunctionArgs) => {
|
||||
//resizable settings
|
||||
const resizeSettings = await getResizableRunSettings(request);
|
||||
|
||||
return typedjson({
|
||||
...result,
|
||||
return {
|
||||
run: result.run,
|
||||
trace: result.trace,
|
||||
maximumLiveReloadingSetting: env.MAXIMUM_LIVE_RELOADING_EVENTS,
|
||||
resizeSettings,
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
function getSpanId(location: Location<any>): string | undefined {
|
||||
@@ -97,7 +103,8 @@ function getSpanId(location: Location<any>): string | undefined {
|
||||
}
|
||||
|
||||
export default function Page() {
|
||||
const { run, trace, resizeSettings } = useTypedLoaderData<typeof loader>();
|
||||
const { run, trace, resizeSettings, maximumLiveReloadingSetting } =
|
||||
useLoaderData<typeof loader>();
|
||||
const organization = useOrganization();
|
||||
const project = useProject();
|
||||
const user = useUser();
|
||||
@@ -167,6 +174,7 @@ export default function Page() {
|
||||
}
|
||||
|
||||
const { events, parentRunFriendlyId, duration, rootSpanStatus, rootStartedAt } = trace;
|
||||
const shouldLiveReload = events.length <= maximumLiveReloadingSetting;
|
||||
|
||||
const changeToSpan = useDebounce((selectedSpan: string) => {
|
||||
replaceSearchParam("span", selectedSpan);
|
||||
@@ -175,6 +183,7 @@ export default function Page() {
|
||||
const revalidator = useRevalidator();
|
||||
const streamedEvents = useEventSource(v3RunStreamingPath(organization, project, run), {
|
||||
event: "message",
|
||||
disabled: !shouldLiveReload,
|
||||
});
|
||||
useEffect(() => {
|
||||
if (streamedEvents !== null) {
|
||||
@@ -252,8 +261,10 @@ export default function Page() {
|
||||
}}
|
||||
totalDuration={duration}
|
||||
rootSpanStatus={rootSpanStatus}
|
||||
rootStartedAt={rootStartedAt}
|
||||
rootStartedAt={rootStartedAt ? new Date(rootStartedAt) : undefined}
|
||||
environmentType={run.environment.type}
|
||||
shouldLiveReload={shouldLiveReload}
|
||||
maximumLiveReloadingSetting={maximumLiveReloadingSetting}
|
||||
/>
|
||||
</ResizablePanel>
|
||||
<ResizableHandle withHandle />
|
||||
@@ -274,7 +285,7 @@ export default function Page() {
|
||||
}
|
||||
|
||||
type TasksTreeViewProps = {
|
||||
events: RunEvent[];
|
||||
events: TraceEvent[];
|
||||
selectedId?: string;
|
||||
parentRunFriendlyId?: string;
|
||||
onSelectedIdChanged: (selectedId: string | undefined) => void;
|
||||
@@ -282,6 +293,8 @@ type TasksTreeViewProps = {
|
||||
rootSpanStatus: "executing" | "completed" | "failed";
|
||||
rootStartedAt: Date | undefined;
|
||||
environmentType: RuntimeEnvironmentType;
|
||||
shouldLiveReload: boolean;
|
||||
maximumLiveReloadingSetting: number;
|
||||
};
|
||||
|
||||
function TasksTreeView({
|
||||
@@ -293,6 +306,8 @@ function TasksTreeView({
|
||||
rootSpanStatus,
|
||||
rootStartedAt,
|
||||
environmentType,
|
||||
shouldLiveReload,
|
||||
maximumLiveReloadingSetting,
|
||||
}: TasksTreeViewProps) {
|
||||
const [filterText, setFilterText] = useState("");
|
||||
const [errorsOnly, setErrorsOnly] = useState(false);
|
||||
@@ -367,7 +382,11 @@ function TasksTreeView({
|
||||
This is the root task
|
||||
</Paragraph>
|
||||
)}
|
||||
<LiveReloadingStatus rootSpanCompleted={rootSpanStatus !== "executing"} />
|
||||
<LiveReloadingStatus
|
||||
rootSpanCompleted={rootSpanStatus !== "executing"}
|
||||
isLiveReloading={shouldLiveReload}
|
||||
settingValue={maximumLiveReloadingSetting}
|
||||
/>
|
||||
</div>
|
||||
<TreeView
|
||||
parentRef={parentRef}
|
||||
@@ -750,7 +769,7 @@ function TimelineView({
|
||||
);
|
||||
}
|
||||
|
||||
function NodeText({ node }: { node: RunEvent }) {
|
||||
function NodeText({ node }: { node: TraceEvent }) {
|
||||
const className = "truncate";
|
||||
return (
|
||||
<Paragraph variant="small" className={cn(className)}>
|
||||
@@ -759,7 +778,7 @@ function NodeText({ node }: { node: RunEvent }) {
|
||||
);
|
||||
}
|
||||
|
||||
function NodeStatusIcon({ node }: { node: RunEvent }) {
|
||||
function NodeStatusIcon({ node }: { node: TraceEvent }) {
|
||||
if (node.data.level !== "TRACE") return null;
|
||||
if (node.data.style.variant !== "primary") return null;
|
||||
|
||||
@@ -834,16 +853,40 @@ function ShowParentLink({ runFriendlyId }: { runFriendlyId: string }) {
|
||||
);
|
||||
}
|
||||
|
||||
function LiveReloadingStatus({ rootSpanCompleted }: { rootSpanCompleted: boolean }) {
|
||||
function LiveReloadingStatus({
|
||||
rootSpanCompleted,
|
||||
isLiveReloading,
|
||||
settingValue,
|
||||
}: {
|
||||
rootSpanCompleted: boolean;
|
||||
isLiveReloading: boolean;
|
||||
settingValue: number;
|
||||
}) {
|
||||
if (rootSpanCompleted) return null;
|
||||
|
||||
return (
|
||||
<div className="flex items-center gap-1">
|
||||
<PulsingDot />
|
||||
<Paragraph variant="extra-small" className="whitespace-nowrap text-blue-500">
|
||||
Live reloading
|
||||
</Paragraph>
|
||||
</div>
|
||||
<>
|
||||
{isLiveReloading ? (
|
||||
<div className="flex items-center gap-1">
|
||||
<PulsingDot />
|
||||
<Paragraph variant="extra-small" className="whitespace-nowrap text-blue-500">
|
||||
Live reloading
|
||||
</Paragraph>
|
||||
</div>
|
||||
) : (
|
||||
<SimpleTooltip
|
||||
content={`Live reloading is disabled because you've exceeded ${settingValue} logs.`}
|
||||
button={
|
||||
<div className="flex items-center gap-1">
|
||||
<BoltSlashIcon className="size-3.5 text-text-dimmed" />
|
||||
<Paragraph variant="extra-small" className="whitespace-nowrap text-text-dimmed">
|
||||
Live reloading disabled
|
||||
</Paragraph>
|
||||
</div>
|
||||
}
|
||||
></SimpleTooltip>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -862,7 +905,7 @@ function SpanWithDuration({
|
||||
showDuration,
|
||||
node,
|
||||
...props
|
||||
}: Timeline.SpanProps & { node: RunEvent; showDuration: boolean }) {
|
||||
}: Timeline.SpanProps & { node: TraceEvent; showDuration: boolean }) {
|
||||
return (
|
||||
<Timeline.Span {...props}>
|
||||
<motion.div
|
||||
|
||||
@@ -4,6 +4,7 @@ import { SemanticResourceAttributes } from "@opentelemetry/semantic-conventions"
|
||||
import {
|
||||
ExceptionEventProperties,
|
||||
ExceptionSpanEvent,
|
||||
NULL_SENTINEL,
|
||||
PRIMARY_VARIANT,
|
||||
SemanticInternalAttributes,
|
||||
SpanEvent,
|
||||
@@ -14,7 +15,6 @@ import {
|
||||
correctErrorStackTrace,
|
||||
createPacketAttributesAsJson,
|
||||
flattenAttributes,
|
||||
NULL_SENTINEL,
|
||||
isExceptionSpanEvent,
|
||||
omit,
|
||||
unflattenAttributes,
|
||||
@@ -23,14 +23,15 @@ import { Prisma, TaskEvent, TaskEventStatus, type TaskEventKind } from "@trigger
|
||||
import Redis, { RedisOptions } from "ioredis";
|
||||
import { createHash } from "node:crypto";
|
||||
import { EventEmitter } from "node:stream";
|
||||
import { Gauge } from "prom-client";
|
||||
import { $replica, PrismaClient, PrismaReplicaClient, prisma } from "~/db.server";
|
||||
import { env } from "~/env.server";
|
||||
import { metricsRegister } from "~/metrics.server";
|
||||
import { AuthenticatedEnvironment } from "~/services/apiAuth.server";
|
||||
import { logger } from "~/services/logger.server";
|
||||
import { DynamicFlushScheduler } from "./dynamicFlushScheduler.server";
|
||||
import { singleton } from "~/utils/singleton";
|
||||
import { Gauge } from "prom-client";
|
||||
import { metricsRegister } from "~/metrics.server";
|
||||
import { DynamicFlushScheduler } from "./dynamicFlushScheduler.server";
|
||||
import { startActiveSpan } from "./tracer.server";
|
||||
|
||||
export type CreatableEvent = Omit<
|
||||
Prisma.TaskEventCreateInput,
|
||||
@@ -374,78 +375,100 @@ export class EventRepository {
|
||||
}
|
||||
|
||||
public async getTraceSummary(traceId: string): Promise<TraceSummary | undefined> {
|
||||
const events = await this.readReplica.taskEvent.findMany({
|
||||
select: {
|
||||
id: true,
|
||||
spanId: true,
|
||||
parentId: true,
|
||||
runId: true,
|
||||
idempotencyKey: true,
|
||||
message: true,
|
||||
style: true,
|
||||
startTime: true,
|
||||
duration: true,
|
||||
isError: true,
|
||||
isPartial: true,
|
||||
isCancelled: true,
|
||||
level: true,
|
||||
events: true,
|
||||
environmentType: true,
|
||||
},
|
||||
where: {
|
||||
traceId,
|
||||
},
|
||||
orderBy: {
|
||||
startTime: "asc",
|
||||
},
|
||||
});
|
||||
return await startActiveSpan("getTraceSummary", async (span) => {
|
||||
const events = await this.readReplica.taskEvent.findMany({
|
||||
select: {
|
||||
id: true,
|
||||
spanId: true,
|
||||
parentId: true,
|
||||
runId: true,
|
||||
idempotencyKey: true,
|
||||
message: true,
|
||||
style: true,
|
||||
startTime: true,
|
||||
duration: true,
|
||||
isError: true,
|
||||
isPartial: true,
|
||||
isCancelled: true,
|
||||
level: true,
|
||||
events: true,
|
||||
environmentType: true,
|
||||
},
|
||||
where: {
|
||||
traceId,
|
||||
},
|
||||
orderBy: {
|
||||
startTime: "asc",
|
||||
},
|
||||
});
|
||||
|
||||
const preparedEvents = removeDuplicateEvents(events.map(prepareEvent));
|
||||
let preparedEvents: Array<PreparedEvent> = [];
|
||||
const eventsBySpanId = new Map<string, PreparedEvent>();
|
||||
|
||||
const spans = preparedEvents.map((event) => {
|
||||
const ancestorCancelled = isAncestorCancelled(preparedEvents, event.spanId);
|
||||
const duration = calculateDurationIfAncestorIsCancelled(
|
||||
preparedEvents,
|
||||
event.spanId,
|
||||
event.duration
|
||||
);
|
||||
for (const event of events) {
|
||||
preparedEvents.push(prepareEvent(event));
|
||||
}
|
||||
|
||||
for (const event of preparedEvents) {
|
||||
const existingEvent = eventsBySpanId.get(event.spanId);
|
||||
|
||||
if (!existingEvent) {
|
||||
eventsBySpanId.set(event.spanId, event);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (event.isCancelled || !event.isPartial) {
|
||||
eventsBySpanId.set(event.spanId, event);
|
||||
}
|
||||
}
|
||||
|
||||
preparedEvents = Array.from(eventsBySpanId.values());
|
||||
|
||||
const spans = preparedEvents.map((event) => {
|
||||
const ancestorCancelled = isAncestorCancelled(eventsBySpanId, event.spanId);
|
||||
const duration = calculateDurationIfAncestorIsCancelled(
|
||||
eventsBySpanId,
|
||||
event.spanId,
|
||||
event.duration
|
||||
);
|
||||
|
||||
return {
|
||||
recordId: event.id,
|
||||
id: event.spanId,
|
||||
parentId: event.parentId ?? undefined,
|
||||
runId: event.runId,
|
||||
idempotencyKey: event.idempotencyKey,
|
||||
data: {
|
||||
message: event.message,
|
||||
style: event.style,
|
||||
duration,
|
||||
isError: event.isError,
|
||||
isPartial: ancestorCancelled ? false : event.isPartial,
|
||||
isCancelled: event.isCancelled === true ? true : event.isPartial && ancestorCancelled,
|
||||
startTime: getDateFromNanoseconds(event.startTime),
|
||||
level: event.level,
|
||||
events: event.events,
|
||||
environmentType: event.environmentType,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
const rootSpanId = events.find((event) => !event.parentId);
|
||||
if (!rootSpanId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const rootSpan = spans.find((span) => span.id === rootSpanId.spanId);
|
||||
|
||||
if (!rootSpan) {
|
||||
return;
|
||||
}
|
||||
|
||||
return {
|
||||
recordId: event.id,
|
||||
id: event.spanId,
|
||||
parentId: event.parentId ?? undefined,
|
||||
runId: event.runId,
|
||||
idempotencyKey: event.idempotencyKey,
|
||||
data: {
|
||||
message: event.message,
|
||||
style: event.style,
|
||||
duration,
|
||||
isError: event.isError,
|
||||
isPartial: ancestorCancelled ? false : event.isPartial,
|
||||
isCancelled: event.isCancelled === true ? true : event.isPartial && ancestorCancelled,
|
||||
startTime: getDateFromNanoseconds(event.startTime),
|
||||
level: event.level,
|
||||
events: event.events,
|
||||
environmentType: event.environmentType,
|
||||
},
|
||||
rootSpan,
|
||||
spans,
|
||||
};
|
||||
});
|
||||
|
||||
const rootSpanId = events.find((event) => !event.parentId);
|
||||
if (!rootSpanId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const rootSpan = spans.find((span) => span.id === rootSpanId.spanId);
|
||||
|
||||
if (!rootSpan) {
|
||||
return;
|
||||
}
|
||||
|
||||
return {
|
||||
rootSpan,
|
||||
spans,
|
||||
};
|
||||
}
|
||||
|
||||
// A Span can be cancelled if it is partial and has a parent that is cancelled
|
||||
@@ -973,34 +996,38 @@ function prepareEvent(event: QueriedEvent): PreparedEvent {
|
||||
}
|
||||
|
||||
function parseEventsField(events: Prisma.JsonValue): SpanEvents {
|
||||
const eventsUnflattened = events
|
||||
const unsafe = events
|
||||
? (events as any[]).map((e) => ({
|
||||
...e,
|
||||
properties: unflattenAttributes(e.properties as Attributes),
|
||||
}))
|
||||
: undefined;
|
||||
|
||||
const spanEvents = SpanEvents.safeParse(eventsUnflattened);
|
||||
|
||||
if (spanEvents.success) {
|
||||
return spanEvents.data;
|
||||
}
|
||||
|
||||
return [];
|
||||
return unsafe as SpanEvents;
|
||||
}
|
||||
|
||||
function parseStyleField(style: Prisma.JsonValue): TaskEventStyle {
|
||||
const parsedStyle = TaskEventStyle.safeParse(unflattenAttributes(style as Attributes));
|
||||
const unsafe = unflattenAttributes(style as Attributes);
|
||||
|
||||
if (parsedStyle.success) {
|
||||
return parsedStyle.data;
|
||||
if (!unsafe) {
|
||||
return {};
|
||||
}
|
||||
|
||||
if (typeof unsafe === "object") {
|
||||
return Object.assign(
|
||||
{
|
||||
icon: undefined,
|
||||
variant: undefined,
|
||||
},
|
||||
unsafe
|
||||
) as TaskEventStyle;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
function isAncestorCancelled(events: PreparedEvent[], spanId: string) {
|
||||
const event = events.find((event) => event.spanId === spanId);
|
||||
function isAncestorCancelled(events: Map<string, PreparedEvent>, spanId: string) {
|
||||
const event = events.get(spanId);
|
||||
|
||||
if (!event) {
|
||||
return false;
|
||||
@@ -1018,11 +1045,11 @@ function isAncestorCancelled(events: PreparedEvent[], spanId: string) {
|
||||
}
|
||||
|
||||
function calculateDurationIfAncestorIsCancelled(
|
||||
events: PreparedEvent[],
|
||||
events: Map<string, PreparedEvent>,
|
||||
spanId: string,
|
||||
defaultDuration: number
|
||||
) {
|
||||
const event = events.find((event) => event.spanId === spanId);
|
||||
const event = events.get(spanId);
|
||||
|
||||
if (!event) {
|
||||
return defaultDuration;
|
||||
@@ -1054,8 +1081,9 @@ function calculateDurationIfAncestorIsCancelled(
|
||||
return defaultDuration;
|
||||
}
|
||||
|
||||
function findFirstCancelledAncestor(events: PreparedEvent[], spanId: string) {
|
||||
const event = events.find((event) => event.spanId === spanId);
|
||||
function findFirstCancelledAncestor(events: Map<string, PreparedEvent>, spanId: string) {
|
||||
const event = events.get(spanId);
|
||||
|
||||
if (!event) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -138,8 +138,19 @@ function createCoordinatorNamespace(io: Server) {
|
||||
await sharedQueueTasks.taskRunHeartbeat(message.runId);
|
||||
},
|
||||
CHECKPOINT_CREATED: async (message) => {
|
||||
const createCheckpoint = new CreateCheckpointService();
|
||||
await createCheckpoint.call(message);
|
||||
try {
|
||||
const createCheckpoint = new CreateCheckpointService();
|
||||
const result = await createCheckpoint.call(message);
|
||||
|
||||
return { keepRunAlive: result?.keepRunAlive ?? false };
|
||||
} catch (error) {
|
||||
logger.error("Error while creating checkpoint", {
|
||||
rawMessage: message,
|
||||
error: error instanceof Error ? error.message : error,
|
||||
});
|
||||
|
||||
return { keepRunAlive: false };
|
||||
}
|
||||
},
|
||||
CREATE_WORKER: async (message) => {
|
||||
try {
|
||||
|
||||
@@ -1625,7 +1625,7 @@ function getMarQSClient() {
|
||||
defaultEnvConcurrency: env.DEFAULT_ENV_EXECUTION_CONCURRENCY_LIMIT,
|
||||
defaultOrgConcurrency: env.DEFAULT_ORG_EXECUTION_CONCURRENCY_LIMIT,
|
||||
visibilityTimeoutInMs: 120 * 1000, // 2 minutes,
|
||||
enableRebalancing: !env.MARQS_DISABLE_REBALANCING,
|
||||
enableRebalancing: false,
|
||||
});
|
||||
} else {
|
||||
console.warn(
|
||||
|
||||
@@ -17,7 +17,6 @@ import {
|
||||
BackgroundWorkerTask,
|
||||
RuntimeEnvironment,
|
||||
TaskRun,
|
||||
TaskRunAttemptStatus,
|
||||
TaskRunStatus,
|
||||
} from "@trigger.dev/database";
|
||||
import { z } from "zod";
|
||||
@@ -43,6 +42,7 @@ import { generateJWTTokenForEnvironment } from "~/services/apiAuth.server";
|
||||
import { EnvironmentVariable } from "../environmentVariables/repository";
|
||||
import { machinePresetFromConfig } from "../machinePresets.server";
|
||||
import { env } from "~/env.server";
|
||||
import { isFinalAttemptStatus, isFinalRunStatus } from "../taskStatus";
|
||||
|
||||
const WithTraceContext = z.object({
|
||||
traceparent: z.string().optional(),
|
||||
@@ -962,19 +962,7 @@ class SharedQueueTasks {
|
||||
}
|
||||
|
||||
if (setToExecuting) {
|
||||
const FINAL_RUN_STATUSES: TaskRunStatus[] = [
|
||||
"CANCELED",
|
||||
"COMPLETED_SUCCESSFULLY",
|
||||
"COMPLETED_WITH_ERRORS",
|
||||
"INTERRUPTED",
|
||||
"SYSTEM_FAILURE",
|
||||
];
|
||||
const FINAL_ATTEMPT_STATUSES: TaskRunAttemptStatus[] = ["CANCELED", "COMPLETED", "FAILED"];
|
||||
|
||||
if (
|
||||
FINAL_ATTEMPT_STATUSES.includes(attempt.status) ||
|
||||
FINAL_RUN_STATUSES.includes(attempt.taskRun.status)
|
||||
) {
|
||||
if (isFinalAttemptStatus(attempt.status) || isFinalRunStatus(attempt.taskRun.status)) {
|
||||
logger.error("Status already in final state", {
|
||||
attempt: {
|
||||
id: attempt.id,
|
||||
|
||||
@@ -82,7 +82,7 @@ function getMarQSClient() {
|
||||
defaultEnvConcurrency: env.V2_MARQS_DEFAULT_ENV_CONCURRENCY, // this is so we aren't limited by the environment concurrency
|
||||
defaultOrgConcurrency: env.DEFAULT_ORG_EXECUTION_CONCURRENCY_LIMIT,
|
||||
visibilityTimeoutInMs: env.V2_MARQS_VISIBILITY_TIMEOUT_MS, // 15 minutes
|
||||
enableRebalancing: env.V2_MARQS_CONSUMER_POOL_ENABLED === "1",
|
||||
enableRebalancing: false,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import { logger } from "~/services/logger.server";
|
||||
|
||||
import { PrismaClientOrTransaction, prisma } from "~/db.server";
|
||||
import { ResumeTaskRunDependenciesService } from "./resumeTaskRunDependencies.server";
|
||||
import { CANCELLABLE_STATUSES } from "./cancelTaskRun.server";
|
||||
import { isCancellableRunStatus } from "../taskStatus";
|
||||
|
||||
export class CancelAttemptService extends BaseService {
|
||||
public async call(
|
||||
@@ -55,7 +55,7 @@ export class CancelAttemptService extends BaseService {
|
||||
taskRun: {
|
||||
update: {
|
||||
data: {
|
||||
status: CANCELLABLE_STATUSES.includes(taskRunAttempt.taskRun.status)
|
||||
status: isCancellableRunStatus(taskRunAttempt.taskRun.status)
|
||||
? "INTERRUPTED"
|
||||
: undefined,
|
||||
},
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Prisma, TaskRun, TaskRunAttemptStatus, TaskRunStatus } from "@trigger.dev/database";
|
||||
import { Prisma, TaskRun } from "@trigger.dev/database";
|
||||
import assertNever from "assert-never";
|
||||
import { logger } from "~/services/logger.server";
|
||||
import { marqs } from "~/v3/marqs/index.server";
|
||||
@@ -7,22 +7,7 @@ import { socketIo } from "../handleSocketIo.server";
|
||||
import { devPubSub } from "../marqs/devPubSub.server";
|
||||
import { BaseService } from "./baseService.server";
|
||||
import { CancelAttemptService } from "./cancelAttempt.server";
|
||||
|
||||
export const CANCELLABLE_STATUSES: Array<TaskRunStatus> = [
|
||||
"PENDING",
|
||||
"WAITING_FOR_DEPLOY",
|
||||
"EXECUTING",
|
||||
"PAUSED",
|
||||
"WAITING_TO_RESUME",
|
||||
"PAUSED",
|
||||
"RETRYING_AFTER_FAILURE",
|
||||
];
|
||||
|
||||
const CANCELLABLE_ATTEMPT_STATUSES: Array<TaskRunAttemptStatus> = [
|
||||
"EXECUTING",
|
||||
"PAUSED",
|
||||
"PENDING",
|
||||
];
|
||||
import { CANCELLABLE_ATTEMPT_STATUSES, isCancellableRunStatus } from "../taskStatus";
|
||||
|
||||
type ExtendedTaskRun = Prisma.TaskRunGetPayload<{
|
||||
include: {
|
||||
@@ -53,7 +38,11 @@ export class CancelTaskRunService extends BaseService {
|
||||
};
|
||||
|
||||
// Make sure the task run is in a cancellable state
|
||||
if (!CANCELLABLE_STATUSES.includes(taskRun.status)) {
|
||||
if (!isCancellableRunStatus(taskRun.status)) {
|
||||
logger.error("Task run is not in a cancellable state", {
|
||||
runId: taskRun.id,
|
||||
status: taskRun.status,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,27 +1,11 @@
|
||||
import {
|
||||
TaskRun,
|
||||
TaskRunAttempt,
|
||||
TaskRunAttemptStatus,
|
||||
TaskRunStatus,
|
||||
} from "@trigger.dev/database";
|
||||
import { TaskRun, TaskRunAttempt } from "@trigger.dev/database";
|
||||
import { eventRepository } from "../eventRepository.server";
|
||||
import { marqs } from "~/v3/marqs/index.server";
|
||||
import { BaseService } from "./baseService.server";
|
||||
import { logger } from "~/services/logger.server";
|
||||
import { AuthenticatedEnvironment } from "~/services/apiAuth.server";
|
||||
import { ResumeTaskRunDependenciesService } from "./resumeTaskRunDependencies.server";
|
||||
|
||||
export const CRASHABLE_RUN_STATUSES: Array<TaskRunStatus> = [
|
||||
"PENDING",
|
||||
"WAITING_FOR_DEPLOY",
|
||||
"EXECUTING",
|
||||
"PAUSED",
|
||||
"WAITING_TO_RESUME",
|
||||
"PAUSED",
|
||||
"RETRYING_AFTER_FAILURE",
|
||||
];
|
||||
|
||||
const CRASHABLE_ATTEMPT_STATUSES: Array<TaskRunAttemptStatus> = ["EXECUTING", "PAUSED", "PENDING"];
|
||||
import { CRASHABLE_ATTEMPT_STATUSES, isCrashableRunStatus } from "../taskStatus";
|
||||
|
||||
export type CrashTaskRunServiceOptions = {
|
||||
reason?: string;
|
||||
@@ -52,7 +36,8 @@ export class CrashTaskRunService extends BaseService {
|
||||
}
|
||||
|
||||
// Make sure the task run is in a crashable state
|
||||
if (!CRASHABLE_RUN_STATUSES.includes(taskRun.status)) {
|
||||
if (!isCrashableRunStatus(taskRun.status)) {
|
||||
logger.error("Task run is not in a crashable state", { runId, status: taskRun.status });
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,19 +1,13 @@
|
||||
import { CoordinatorToPlatformMessages } from "@trigger.dev/core/v3";
|
||||
import type { InferSocketMessageSchema } from "@trigger.dev/core/v3/zodSocket";
|
||||
import type {
|
||||
CheckpointRestoreEvent,
|
||||
TaskRunAttemptStatus,
|
||||
TaskRunStatus,
|
||||
} from "@trigger.dev/database";
|
||||
import type { Checkpoint, CheckpointRestoreEvent } from "@trigger.dev/database";
|
||||
import { logger } from "~/services/logger.server";
|
||||
import { generateFriendlyId } from "../friendlyIdentifiers";
|
||||
import { marqs } from "~/v3/marqs/index.server";
|
||||
import { CreateCheckpointRestoreEventService } from "./createCheckpointRestoreEvent.server";
|
||||
import { BaseService } from "./baseService.server";
|
||||
import { CrashTaskRunService } from "./crashTaskRun.server";
|
||||
|
||||
const FREEZABLE_RUN_STATUSES: TaskRunStatus[] = ["EXECUTING", "RETRYING_AFTER_FAILURE"];
|
||||
const FREEZABLE_ATTEMPT_STATUSES: TaskRunAttemptStatus[] = ["EXECUTING", "FAILED"];
|
||||
import { isFinalRunStatus, isFreezableAttemptStatus, isFreezableRunStatus } from "../taskStatus";
|
||||
|
||||
export class CreateCheckpointService extends BaseService {
|
||||
public async call(
|
||||
@@ -21,7 +15,14 @@ export class CreateCheckpointService extends BaseService {
|
||||
InferSocketMessageSchema<typeof CoordinatorToPlatformMessages, "CHECKPOINT_CREATED">,
|
||||
"version"
|
||||
>
|
||||
) {
|
||||
): Promise<
|
||||
| {
|
||||
checkpoint: Checkpoint;
|
||||
event: CheckpointRestoreEvent;
|
||||
keepRunAlive: boolean;
|
||||
}
|
||||
| undefined
|
||||
> {
|
||||
logger.debug(`Creating checkpoint`, params);
|
||||
|
||||
const attempt = await this._prisma.taskRunAttempt.findUnique({
|
||||
@@ -49,8 +50,8 @@ export class CreateCheckpointService extends BaseService {
|
||||
}
|
||||
|
||||
if (
|
||||
!FREEZABLE_ATTEMPT_STATUSES.includes(attempt.status) ||
|
||||
!FREEZABLE_RUN_STATUSES.includes(attempt.taskRun.status)
|
||||
!isFreezableAttemptStatus(attempt.status) ||
|
||||
!isFreezableRunStatus(attempt.taskRun.status)
|
||||
) {
|
||||
logger.error("Unfreezable state", {
|
||||
attempt: {
|
||||
@@ -115,7 +116,9 @@ export class CreateCheckpointService extends BaseService {
|
||||
});
|
||||
|
||||
const { reason } = params;
|
||||
|
||||
let checkpointEvent: CheckpointRestoreEvent | undefined;
|
||||
let keepRunAlive = false;
|
||||
|
||||
switch (reason.type) {
|
||||
case "WAIT_FOR_DURATION": {
|
||||
@@ -131,7 +134,12 @@ export class CreateCheckpointService extends BaseService {
|
||||
dependencyFriendlyRunId: reason.friendlyId,
|
||||
});
|
||||
|
||||
await marqs?.acknowledgeMessage(attempt.taskRunId);
|
||||
keepRunAlive = await this.#isRunCompleted(reason.friendlyId);
|
||||
|
||||
if (!keepRunAlive) {
|
||||
await marqs?.acknowledgeMessage(attempt.taskRunId);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case "WAIT_FOR_BATCH": {
|
||||
@@ -140,7 +148,12 @@ export class CreateCheckpointService extends BaseService {
|
||||
batchDependencyFriendlyId: reason.batchFriendlyId,
|
||||
});
|
||||
|
||||
await marqs?.acknowledgeMessage(attempt.taskRunId);
|
||||
keepRunAlive = await this.#isBatchCompleted(reason.batchFriendlyId);
|
||||
|
||||
if (!keepRunAlive) {
|
||||
await marqs?.acknowledgeMessage(attempt.taskRunId);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case "RETRYING_AFTER_FAILURE": {
|
||||
@@ -180,6 +193,37 @@ export class CreateCheckpointService extends BaseService {
|
||||
return {
|
||||
checkpoint,
|
||||
event: checkpointEvent,
|
||||
keepRunAlive,
|
||||
};
|
||||
}
|
||||
|
||||
async #isBatchCompleted(friendlyId: string): Promise<boolean> {
|
||||
const batch = await this._prisma.batchTaskRun.findUnique({
|
||||
where: {
|
||||
friendlyId,
|
||||
},
|
||||
});
|
||||
|
||||
if (!batch) {
|
||||
logger.error("Batch not found", { friendlyId });
|
||||
return false;
|
||||
}
|
||||
|
||||
return batch.status === "COMPLETED";
|
||||
}
|
||||
|
||||
async #isRunCompleted(friendlyId: string): Promise<boolean> {
|
||||
const run = await this._prisma.taskRun.findUnique({
|
||||
where: {
|
||||
friendlyId,
|
||||
},
|
||||
});
|
||||
|
||||
if (!run) {
|
||||
logger.error("Run not found", { friendlyId });
|
||||
return false;
|
||||
}
|
||||
|
||||
return isFinalRunStatus(run.status);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
import { TaskRunAttemptStatus, TaskRunStatus, type Checkpoint } from "@trigger.dev/database";
|
||||
import { type Checkpoint } from "@trigger.dev/database";
|
||||
import { logger } from "~/services/logger.server";
|
||||
import { socketIo } from "../handleSocketIo.server";
|
||||
import { machinePresetFromConfig } from "../machinePresets.server";
|
||||
import { BaseService } from "./baseService.server";
|
||||
import { CreateCheckpointRestoreEventService } from "./createCheckpointRestoreEvent.server";
|
||||
|
||||
const RESTORABLE_RUN_STATUSES: TaskRunStatus[] = ["WAITING_TO_RESUME"];
|
||||
const RESTORABLE_ATTEMPT_STATUSES: TaskRunAttemptStatus[] = ["PAUSED"];
|
||||
import { isRestorableAttemptStatus, isRestorableRunStatus } from "../taskStatus";
|
||||
|
||||
export class RestoreCheckpointService extends BaseService {
|
||||
public async call(params: {
|
||||
@@ -51,10 +49,7 @@ export class RestoreCheckpointService extends BaseService {
|
||||
|
||||
const checkpoint = checkpointEvent.checkpoint;
|
||||
|
||||
const runIsRestorable = RESTORABLE_RUN_STATUSES.includes(checkpoint.run.status);
|
||||
const attemptIsRestorable = RESTORABLE_ATTEMPT_STATUSES.includes(checkpoint.attempt.status);
|
||||
|
||||
if (!runIsRestorable) {
|
||||
if (!isRestorableRunStatus(checkpoint.run.status)) {
|
||||
logger.error("Run is unrestorable", {
|
||||
eventId: params.eventId,
|
||||
runId: checkpoint.runId,
|
||||
@@ -64,7 +59,7 @@ export class RestoreCheckpointService extends BaseService {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!attemptIsRestorable && !params.isRetry) {
|
||||
if (!isRestorableAttemptStatus(checkpoint.attempt.status) && !params.isRetry) {
|
||||
logger.error("Attempt is unrestorable", {
|
||||
eventId: params.eventId,
|
||||
runId: checkpoint.runId,
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
import type { TaskRunAttemptStatus, TaskRunStatus } from "@trigger.dev/database";
|
||||
|
||||
export const CANCELLABLE_RUN_STATUSES: TaskRunStatus[] = [
|
||||
"PENDING",
|
||||
"WAITING_FOR_DEPLOY",
|
||||
"EXECUTING",
|
||||
"PAUSED",
|
||||
"WAITING_TO_RESUME",
|
||||
"PAUSED",
|
||||
"RETRYING_AFTER_FAILURE",
|
||||
];
|
||||
export const CANCELLABLE_ATTEMPT_STATUSES: TaskRunAttemptStatus[] = [
|
||||
"EXECUTING",
|
||||
"PAUSED",
|
||||
"PENDING",
|
||||
];
|
||||
|
||||
export function isCancellableRunStatus(status: TaskRunStatus): boolean {
|
||||
return CANCELLABLE_RUN_STATUSES.includes(status);
|
||||
}
|
||||
export function isCancellableAttemptStatus(status: TaskRunAttemptStatus): boolean {
|
||||
return CANCELLABLE_ATTEMPT_STATUSES.includes(status);
|
||||
}
|
||||
|
||||
export const CRASHABLE_RUN_STATUSES: TaskRunStatus[] = CANCELLABLE_RUN_STATUSES;
|
||||
export const CRASHABLE_ATTEMPT_STATUSES: TaskRunAttemptStatus[] = CANCELLABLE_ATTEMPT_STATUSES;
|
||||
|
||||
export function isCrashableRunStatus(status: TaskRunStatus): boolean {
|
||||
return CRASHABLE_RUN_STATUSES.includes(status);
|
||||
}
|
||||
export function isCrashableAttemptStatus(status: TaskRunAttemptStatus): boolean {
|
||||
return CRASHABLE_ATTEMPT_STATUSES.includes(status);
|
||||
}
|
||||
|
||||
export const FINAL_RUN_STATUSES: TaskRunStatus[] = [
|
||||
"CANCELED",
|
||||
"COMPLETED_SUCCESSFULLY",
|
||||
"COMPLETED_WITH_ERRORS",
|
||||
"INTERRUPTED",
|
||||
"SYSTEM_FAILURE",
|
||||
];
|
||||
export const FINAL_ATTEMPT_STATUSES: TaskRunAttemptStatus[] = ["CANCELED", "COMPLETED", "FAILED"];
|
||||
|
||||
export const FREEZABLE_RUN_STATUSES: TaskRunStatus[] = ["EXECUTING", "RETRYING_AFTER_FAILURE"];
|
||||
export const FREEZABLE_ATTEMPT_STATUSES: TaskRunAttemptStatus[] = ["EXECUTING", "FAILED"];
|
||||
|
||||
export function isFreezableRunStatus(status: TaskRunStatus): boolean {
|
||||
return FREEZABLE_RUN_STATUSES.includes(status);
|
||||
}
|
||||
export function isFreezableAttemptStatus(status: TaskRunAttemptStatus): boolean {
|
||||
return FREEZABLE_ATTEMPT_STATUSES.includes(status);
|
||||
}
|
||||
|
||||
export function isFinalRunStatus(status: TaskRunStatus): boolean {
|
||||
return FINAL_RUN_STATUSES.includes(status);
|
||||
}
|
||||
export function isFinalAttemptStatus(status: TaskRunAttemptStatus): boolean {
|
||||
return FINAL_ATTEMPT_STATUSES.includes(status);
|
||||
}
|
||||
|
||||
export const RESTORABLE_RUN_STATUSES: TaskRunStatus[] = ["WAITING_TO_RESUME"];
|
||||
export const RESTORABLE_ATTEMPT_STATUSES: TaskRunAttemptStatus[] = ["PAUSED"];
|
||||
|
||||
export function isRestorableRunStatus(status: TaskRunStatus): boolean {
|
||||
return RESTORABLE_RUN_STATUSES.includes(status);
|
||||
}
|
||||
export function isRestorableAttemptStatus(status: TaskRunAttemptStatus): boolean {
|
||||
return RESTORABLE_ATTEMPT_STATUSES.includes(status);
|
||||
}
|
||||
@@ -4,7 +4,10 @@ import {
|
||||
DiagConsoleLogger,
|
||||
DiagLogLevel,
|
||||
Link,
|
||||
Span,
|
||||
SpanKind,
|
||||
SpanOptions,
|
||||
SpanStatusCode,
|
||||
diag,
|
||||
trace,
|
||||
} from "@opentelemetry/api";
|
||||
@@ -76,6 +79,32 @@ class CustomWebappSampler implements Sampler {
|
||||
|
||||
export const tracer = singleton("tracer", getTracer);
|
||||
|
||||
export async function startActiveSpan<T>(
|
||||
name: string,
|
||||
fn: (span: Span) => Promise<T>,
|
||||
options?: SpanOptions
|
||||
): Promise<T> {
|
||||
return tracer.startActiveSpan(name, options ?? {}, async (span) => {
|
||||
try {
|
||||
return await fn(span);
|
||||
} catch (error) {
|
||||
if (error instanceof Error) {
|
||||
span.recordException(error);
|
||||
} else if (typeof error === "string") {
|
||||
span.recordException(new Error(error));
|
||||
} else {
|
||||
span.recordException(new Error(String(error)));
|
||||
}
|
||||
|
||||
span.setStatus({ code: SpanStatusCode.ERROR });
|
||||
|
||||
throw error;
|
||||
} finally {
|
||||
span.end();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getTracer() {
|
||||
if (env.INTERNAL_OTEL_TRACE_DISABLED === "1") {
|
||||
console.log(`🔦 Tracer disabled, returning a noop tracer`);
|
||||
|
||||
+2
-58
@@ -811,17 +811,7 @@ paths:
|
||||
description: Whether to override existing variables or not
|
||||
default: false
|
||||
required: ["variables"]
|
||||
multipart/form-data:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
variables:
|
||||
type: string
|
||||
format: binary
|
||||
override:
|
||||
type: boolean
|
||||
required:
|
||||
- variables
|
||||
|
||||
responses:
|
||||
"200":
|
||||
description: Environment variables imported successfully
|
||||
@@ -864,57 +854,11 @@ paths:
|
||||
source: |-
|
||||
import { envvars } from "@trigger.dev/sdk/v3";
|
||||
|
||||
// Import variables from an array
|
||||
await envvars.upload("proj_yubjwjsfkxnylobaqvqz", "dev", {
|
||||
variables: [
|
||||
{
|
||||
name: "SLACK_API_KEY",
|
||||
value: "slack_123456"
|
||||
}
|
||||
],
|
||||
variables: { SLACK_API_KEY: "slack_key_1234" },
|
||||
override: false
|
||||
});
|
||||
- lang: typescript
|
||||
label: Import variables from a read stream
|
||||
source: |-
|
||||
import { envvars } from "@trigger.dev/sdk/v3";
|
||||
import { createReadStream } from "node:fs";
|
||||
|
||||
// Import variables in dotenv format from a file
|
||||
await envvars.upload("proj_yubjwjsfkxnylobaqvqz", "dev", {
|
||||
variables: createReadStream(".env"),
|
||||
override: false
|
||||
});
|
||||
- lang: typescript
|
||||
label: Import variables from a response
|
||||
source: |-
|
||||
import { envvars } from "@trigger.dev/sdk/v3";
|
||||
|
||||
// Import variables in dotenv format from a response
|
||||
await envvars.upload("proj_yubjwjsfkxnylobaqvqz", "dev", {
|
||||
variables: await fetch("https://example.com/.env"),
|
||||
override: false
|
||||
});
|
||||
- lang: typescript
|
||||
label: Import variables from a Buffer
|
||||
source: |-
|
||||
import { envvars } from "@trigger.dev/sdk/v3";
|
||||
|
||||
// Import variables in dotenv format from a buffer
|
||||
await envvars.upload("proj_yubjwjsfkxnylobaqvqz", "dev", {
|
||||
variables: Buffer.from("SLACK_API_KEY=slack_1234"),
|
||||
override: false
|
||||
});
|
||||
- lang: typescript
|
||||
label: Import variables from a File
|
||||
source: |-
|
||||
import { envvars } from "@trigger.dev/sdk/v3";
|
||||
|
||||
// Import variables in dotenv format from a file
|
||||
await envvars.upload("proj_yubjwjsfkxnylobaqvqz", "dev", {
|
||||
variables: new File(["SLACK_API_KEY=slack_1234"], ".env"),
|
||||
override: false
|
||||
});
|
||||
|
||||
"/api/v1/projects/{projectRef}/envvars/{env}/{name}":
|
||||
parameters:
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
# @trigger.dev/airtable
|
||||
|
||||
## 3.0.0-beta.40
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @trigger.dev/integration-kit@3.0.0-beta.40
|
||||
- @trigger.dev/sdk@3.0.0-beta.40
|
||||
|
||||
## 3.0.0-beta.39
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/airtable",
|
||||
"version": "3.0.0-beta.39",
|
||||
"version": "3.0.0-beta.40",
|
||||
"description": "Trigger.dev integration for airtable",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -25,8 +25,8 @@
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@trigger.dev/integration-kit": "workspace:^3.0.0-beta.39",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.39",
|
||||
"@trigger.dev/integration-kit": "workspace:^3.0.0-beta.40",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.40",
|
||||
"airtable": "^0.12.1",
|
||||
"zod": "3.22.3"
|
||||
},
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
# @trigger.dev/github
|
||||
|
||||
## 3.0.0-beta.40
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @trigger.dev/integration-kit@3.0.0-beta.40
|
||||
- @trigger.dev/sdk@3.0.0-beta.40
|
||||
|
||||
## 3.0.0-beta.39
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/github",
|
||||
"version": "3.0.0-beta.39",
|
||||
"version": "3.0.0-beta.40",
|
||||
"description": "The official GitHub integration for Trigger.dev",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -30,8 +30,8 @@
|
||||
"@octokit/request-error": "^5.0.1",
|
||||
"@octokit/webhooks": "^12.0.10",
|
||||
"octokit": "^3.1.2",
|
||||
"@trigger.dev/integration-kit": "workspace:^3.0.0-beta.39",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.39",
|
||||
"@trigger.dev/integration-kit": "workspace:^3.0.0-beta.40",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.40",
|
||||
"zod": "3.22.3"
|
||||
},
|
||||
"engines": {
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
# @trigger.dev/linear
|
||||
|
||||
## 3.0.0-beta.40
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @trigger.dev/integration-kit@3.0.0-beta.40
|
||||
- @trigger.dev/sdk@3.0.0-beta.40
|
||||
|
||||
## 3.0.0-beta.39
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/linear",
|
||||
"version": "3.0.0-beta.39",
|
||||
"version": "3.0.0-beta.40",
|
||||
"description": "Trigger.dev integration for @linear/sdk",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -26,8 +26,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@linear/sdk": "^8.0.0",
|
||||
"@trigger.dev/integration-kit": "workspace:^3.0.0-beta.39",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.39",
|
||||
"@trigger.dev/integration-kit": "workspace:^3.0.0-beta.40",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.40",
|
||||
"zod": "3.22.3"
|
||||
},
|
||||
"engines": {
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
# @trigger.dev/slack
|
||||
|
||||
## 3.0.0-beta.40
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @trigger.dev/integration-kit@3.0.0-beta.40
|
||||
- @trigger.dev/sdk@3.0.0-beta.40
|
||||
|
||||
## 3.0.0-beta.39
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/openai",
|
||||
"version": "3.0.0-beta.39",
|
||||
"version": "3.0.0-beta.40",
|
||||
"description": "The official OpenAI integration for Trigger.dev",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -42,8 +42,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"openai": "^4.16.1",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.39",
|
||||
"@trigger.dev/integration-kit": "workspace:^3.0.0-beta.39"
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.40",
|
||||
"@trigger.dev/integration-kit": "workspace:^3.0.0-beta.40"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
# @trigger.dev/plain
|
||||
|
||||
## 3.0.0-beta.40
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @trigger.dev/integration-kit@3.0.0-beta.40
|
||||
- @trigger.dev/sdk@3.0.0-beta.40
|
||||
|
||||
## 3.0.0-beta.39
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/plain",
|
||||
"version": "3.0.0-beta.39",
|
||||
"version": "3.0.0-beta.40",
|
||||
"description": "The official Plain.com integration for Trigger.dev",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -24,8 +24,8 @@
|
||||
"build:tsup": "tsup"
|
||||
},
|
||||
"dependencies": {
|
||||
"@trigger.dev/integration-kit": "workspace:^3.0.0-beta.39",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.39",
|
||||
"@trigger.dev/integration-kit": "workspace:^3.0.0-beta.40",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.40",
|
||||
"@team-plain/typescript-sdk": "^2.7.0"
|
||||
},
|
||||
"engines": {
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
# @trigger.dev/replicate
|
||||
|
||||
## 3.0.0-beta.40
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @trigger.dev/integration-kit@3.0.0-beta.40
|
||||
- @trigger.dev/sdk@3.0.0-beta.40
|
||||
|
||||
## 3.0.0-beta.39
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/replicate",
|
||||
"version": "3.0.0-beta.39",
|
||||
"version": "3.0.0-beta.40",
|
||||
"description": "Trigger.dev integration for replicate",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -25,8 +25,8 @@
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@trigger.dev/integration-kit": "workspace:^3.0.0-beta.39",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.39",
|
||||
"@trigger.dev/integration-kit": "workspace:^3.0.0-beta.40",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.40",
|
||||
"replicate": "^0.18.1",
|
||||
"zod": "3.22.3"
|
||||
},
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
# @trigger.dev/resend
|
||||
|
||||
## 3.0.0-beta.40
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @trigger.dev/integration-kit@3.0.0-beta.40
|
||||
- @trigger.dev/sdk@3.0.0-beta.40
|
||||
|
||||
## 3.0.0-beta.39
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/resend",
|
||||
"version": "3.0.0-beta.39",
|
||||
"version": "3.0.0-beta.40",
|
||||
"description": "The official Resend.com integration for Trigger.dev",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -24,8 +24,8 @@
|
||||
"build:tsup": "tsup"
|
||||
},
|
||||
"dependencies": {
|
||||
"@trigger.dev/integration-kit": "workspace:^3.0.0-beta.39",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.39",
|
||||
"@trigger.dev/integration-kit": "workspace:^3.0.0-beta.40",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.40",
|
||||
"resend": "^2.1.0"
|
||||
},
|
||||
"engines": {
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
# @trigger.dev/sendgrid
|
||||
|
||||
## 3.0.0-beta.40
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @trigger.dev/integration-kit@3.0.0-beta.40
|
||||
- @trigger.dev/sdk@3.0.0-beta.40
|
||||
|
||||
## 3.0.0-beta.39
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/sendgrid",
|
||||
"version": "3.0.0-beta.39",
|
||||
"version": "3.0.0-beta.40",
|
||||
"description": "Trigger.dev integration for @sendgrid/mail",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -26,8 +26,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@sendgrid/mail": "^7.7.0",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.39",
|
||||
"@trigger.dev/integration-kit": "workspace:^3.0.0-beta.39"
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.40",
|
||||
"@trigger.dev/integration-kit": "workspace:^3.0.0-beta.40"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16.8.0"
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
# @trigger.dev/shopify
|
||||
|
||||
## 3.0.0-beta.40
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @trigger.dev/integration-kit@3.0.0-beta.40
|
||||
- @trigger.dev/sdk@3.0.0-beta.40
|
||||
|
||||
## 3.0.0-beta.39
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/shopify",
|
||||
"version": "3.0.0-beta.39",
|
||||
"version": "3.0.0-beta.40",
|
||||
"description": "Trigger.dev integration for @shopify/shopify-api",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -26,8 +26,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@shopify/shopify-api": "^8.0.2",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.39",
|
||||
"@trigger.dev/integration-kit": "workspace:^3.0.0-beta.39",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.40",
|
||||
"@trigger.dev/integration-kit": "workspace:^3.0.0-beta.40",
|
||||
"zod": "3.22.3"
|
||||
},
|
||||
"engines": {
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# @trigger.dev/slack
|
||||
|
||||
## 3.0.0-beta.40
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @trigger.dev/sdk@3.0.0-beta.40
|
||||
|
||||
## 3.0.0-beta.39
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/slack",
|
||||
"version": "3.0.0-beta.39",
|
||||
"version": "3.0.0-beta.40",
|
||||
"description": "The official Slack integration for Trigger.dev",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -25,7 +25,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@slack/web-api": "^6.8.1",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.39",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.40",
|
||||
"zod": "3.22.3"
|
||||
},
|
||||
"engines": {
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
# @trigger.dev/stripe
|
||||
|
||||
## 3.0.0-beta.40
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @trigger.dev/integration-kit@3.0.0-beta.40
|
||||
- @trigger.dev/sdk@3.0.0-beta.40
|
||||
|
||||
## 3.0.0-beta.39
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/stripe",
|
||||
"version": "3.0.0-beta.39",
|
||||
"version": "3.0.0-beta.40",
|
||||
"description": "Trigger.dev integration for stripe",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -25,8 +25,8 @@
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@trigger.dev/integration-kit": "workspace:^3.0.0-beta.39",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.39",
|
||||
"@trigger.dev/integration-kit": "workspace:^3.0.0-beta.40",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.40",
|
||||
"stripe": "^12.14.0",
|
||||
"zod": "3.22.3"
|
||||
},
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
# @trigger.dev/supabase
|
||||
|
||||
## 3.0.0-beta.40
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @trigger.dev/integration-kit@3.0.0-beta.40
|
||||
- @trigger.dev/sdk@3.0.0-beta.40
|
||||
|
||||
## 3.0.0-beta.39
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/supabase",
|
||||
"version": "3.0.0-beta.39",
|
||||
"version": "3.0.0-beta.40",
|
||||
"description": "Trigger.dev integration for @supabase/supabase-js",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -26,8 +26,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@supabase/supabase-js": "^2.26.0",
|
||||
"@trigger.dev/integration-kit": "workspace:^3.0.0-beta.39",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.39",
|
||||
"@trigger.dev/integration-kit": "workspace:^3.0.0-beta.40",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.40",
|
||||
"supabase-management-js": "^1.0.0",
|
||||
"zod": "3.22.3"
|
||||
},
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
# @trigger.dev/typeform
|
||||
|
||||
## 3.0.0-beta.40
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @trigger.dev/integration-kit@3.0.0-beta.40
|
||||
- @trigger.dev/sdk@3.0.0-beta.40
|
||||
|
||||
## 3.0.0-beta.39
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/typeform",
|
||||
"version": "3.0.0-beta.39",
|
||||
"version": "3.0.0-beta.40",
|
||||
"description": "The official Typeform integration for Trigger.dev",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -24,8 +24,8 @@
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@trigger.dev/integration-kit": "workspace:^3.0.0-beta.39",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.39",
|
||||
"@trigger.dev/integration-kit": "workspace:^3.0.0-beta.40",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.40",
|
||||
"@typeform/api-client": "^1.8.0",
|
||||
"zod": "3.22.3"
|
||||
},
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# @trigger.dev/astro
|
||||
|
||||
## 3.0.0-beta.40
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @trigger.dev/sdk@3.0.0-beta.40
|
||||
|
||||
## 3.0.0-beta.39
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@trigger.dev/astro",
|
||||
"description": "An Astro-native integration for Trigger.dev background jobs platform",
|
||||
"version": "3.0.0-beta.39",
|
||||
"version": "3.0.0-beta.40",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
"files": [
|
||||
@@ -20,7 +20,7 @@
|
||||
"build:tsup": "tsup"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.39"
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.40"
|
||||
},
|
||||
"devDependencies": {
|
||||
"astro": "^3.0.12",
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
# trigger.dev
|
||||
|
||||
## 3.0.0-beta.40
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 098932ea9: v3: vercel edge runtime support
|
||||
- 9835f4ec5: v3: fix otel flushing causing CLEANUP ack timeout errors by always setting a forceFlushTimeoutMillis value
|
||||
- Updated dependencies [55d1f8c67]
|
||||
- Updated dependencies [098932ea9]
|
||||
- Updated dependencies [9835f4ec5]
|
||||
- @trigger.dev/core@3.0.0-beta.40
|
||||
|
||||
## 3.0.0-beta.39
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "trigger.dev",
|
||||
"version": "3.0.0-beta.39",
|
||||
"version": "3.0.0-beta.40",
|
||||
"description": "A Command-Line Interface for Trigger.dev (v3) projects",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -87,7 +87,7 @@
|
||||
"@opentelemetry/sdk-trace-base": "^1.22.0",
|
||||
"@opentelemetry/sdk-trace-node": "^1.22.0",
|
||||
"@opentelemetry/semantic-conventions": "^1.22.0",
|
||||
"@trigger.dev/core": "workspace:3.0.0-beta.39",
|
||||
"@trigger.dev/core": "workspace:3.0.0-beta.40",
|
||||
"@types/degit": "^2.8.3",
|
||||
"chalk": "^5.2.0",
|
||||
"chokidar": "^3.5.3",
|
||||
|
||||
@@ -178,7 +178,7 @@ export async function readConfig(
|
||||
write: true,
|
||||
format: "cjs",
|
||||
platform: "node",
|
||||
target: ["es2018", "node18"],
|
||||
target: ["es2020", "node18"],
|
||||
outfile: builtConfigFilePath,
|
||||
logLevel: "silent",
|
||||
plugins: [
|
||||
|
||||
@@ -18,6 +18,7 @@ export const tracingSDK = new TracingSDK({
|
||||
url: process.env.OTEL_EXPORTER_OTLP_ENDPOINT ?? "http://0.0.0.0:4318",
|
||||
instrumentations: setupImportedConfig?.instrumentations ?? [],
|
||||
diagLogLevel: (process.env.OTEL_LOG_LEVEL as TracingDiagnosticLogLevel) ?? "none",
|
||||
forceFlushTimeoutMillis: 5_000,
|
||||
});
|
||||
|
||||
export const otelTracer: Tracer = tracingSDK.getTracer("trigger-dev-worker", packageJson.version);
|
||||
|
||||
@@ -863,33 +863,11 @@ class TaskRunProcess {
|
||||
}
|
||||
|
||||
#handleLog(data: Buffer) {
|
||||
if (!this._currentExecution) {
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(
|
||||
`[${this.metadata.version}][${this._currentExecution.run.id}.${
|
||||
this._currentExecution.attempt.number
|
||||
}] ${data.toString()}`
|
||||
);
|
||||
console.log(data.toString());
|
||||
}
|
||||
|
||||
#handleStdErr(data: Buffer) {
|
||||
if (this._isBeingKilled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this._currentExecution) {
|
||||
console.error(`[${this.metadata.version}] ${data.toString()}`);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
console.error(
|
||||
`[${this.metadata.version}][${this._currentExecution.run.id}.${
|
||||
this._currentExecution.attempt.number
|
||||
}] ${data.toString()}`
|
||||
);
|
||||
console.error(data.toString());
|
||||
}
|
||||
|
||||
async kill(signal?: number | NodeJS.Signals, timeoutInMs?: number) {
|
||||
|
||||
@@ -202,18 +202,54 @@ const zodIpc = new ZodIpcConnection({
|
||||
},
|
||||
CLEANUP: async ({ flush, kill }, sender) => {
|
||||
if (kill) {
|
||||
await Promise.all([prodUsageManager.flush(), tracingSDK.flush()]);
|
||||
await flushAll();
|
||||
// Now we need to exit the process
|
||||
await sender.send("READY_TO_DISPOSE", undefined);
|
||||
} else {
|
||||
if (flush) {
|
||||
await Promise.all([prodUsageManager.flush(), tracingSDK.flush()]);
|
||||
await flushAll();
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
async function flushAll(timeoutInMs: number = 10_000) {
|
||||
const now = performance.now();
|
||||
|
||||
console.log(`Flushing at ${now}`);
|
||||
|
||||
await Promise.all([flushUsage(), flushTracingSDK()]);
|
||||
|
||||
const duration = performance.now() - now;
|
||||
|
||||
console.log(`Flushed in ${duration}ms`);
|
||||
}
|
||||
|
||||
async function flushUsage() {
|
||||
const now = performance.now();
|
||||
|
||||
console.log(`Flushing usage at ${now}`);
|
||||
|
||||
await prodUsageManager.flush();
|
||||
|
||||
const duration = performance.now() - now;
|
||||
|
||||
console.log(`Flushed usage in ${duration}ms`);
|
||||
}
|
||||
|
||||
async function flushTracingSDK() {
|
||||
const now = performance.now();
|
||||
|
||||
console.log(`Flushing tracingSDK at ${now}`);
|
||||
|
||||
await tracingSDK.flush();
|
||||
|
||||
const duration = performance.now() - now;
|
||||
|
||||
console.log(`Flushed tracingSDK in ${duration}ms`);
|
||||
}
|
||||
|
||||
// Ignore SIGTERM, handled by entry point
|
||||
process.on("SIGTERM", async () => {});
|
||||
|
||||
|
||||
@@ -16,7 +16,9 @@ export const tracingSDK = new TracingSDK({
|
||||
url: process.env.OTEL_EXPORTER_OTLP_ENDPOINT ?? "http://0.0.0.0:4318",
|
||||
instrumentations: setupImportedConfig?.instrumentations ?? [],
|
||||
diagLogLevel: (process.env.OTEL_LOG_LEVEL as TracingDiagnosticLogLevel) ?? "none",
|
||||
forceFlushTimeoutMillis: 1_000,
|
||||
forceFlushTimeoutMillis: process.env.OTEL_FORCE_FLUSH_TIMEOUT
|
||||
? parseInt(process.env.OTEL_FORCE_FLUSH_TIMEOUT, 10)
|
||||
: 5_000,
|
||||
});
|
||||
|
||||
export const otelTracer: Tracer = tracingSDK.getTracer("trigger-prod-worker", packageJson.version);
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
# create-trigger
|
||||
|
||||
## 3.0.0-beta.40
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [55d1f8c67]
|
||||
- Updated dependencies [098932ea9]
|
||||
- Updated dependencies [9835f4ec5]
|
||||
- @trigger.dev/core@3.0.0-beta.40
|
||||
- @trigger.dev/yalt@3.0.0-beta.40
|
||||
|
||||
## 3.0.0-beta.39
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/cli",
|
||||
"version": "3.0.0-beta.39",
|
||||
"version": "3.0.0-beta.40",
|
||||
"description": "The Trigger.dev CLI",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# @trigger.dev/core-apps
|
||||
|
||||
## 3.0.0-beta.40
|
||||
|
||||
## 3.0.0-beta.39
|
||||
|
||||
## 3.0.0-beta.38
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@trigger.dev/core-apps",
|
||||
"description": "Backend core code used across apps",
|
||||
"version": "3.0.0-beta.39",
|
||||
"version": "3.0.0-beta.40",
|
||||
"private": true,
|
||||
"license": "MIT",
|
||||
"main": "./dist/index.js",
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# @trigger.dev/core-backend
|
||||
|
||||
## 3.0.0-beta.40
|
||||
|
||||
## 3.0.0-beta.39
|
||||
|
||||
## 3.0.0-beta.38
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/core-backend",
|
||||
"version": "3.0.0-beta.39",
|
||||
"version": "3.0.0-beta.40",
|
||||
"description": "Core code used across `@trigger.dev/sdk` and Trigger.dev server",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index.js",
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# internal-platform
|
||||
|
||||
## 3.0.0-beta.40
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 55d1f8c67: Add callback to checkpoint created message
|
||||
- 098932ea9: v3: vercel edge runtime support
|
||||
- 9835f4ec5: v3: fix otel flushing causing CLEANUP ack timeout errors by always setting a forceFlushTimeoutMillis value
|
||||
|
||||
## 3.0.0-beta.39
|
||||
|
||||
## 3.0.0-beta.38
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/core",
|
||||
"version": "3.0.0-beta.39",
|
||||
"version": "3.0.0-beta.40",
|
||||
"description": "Core code used across the Trigger.dev SDK and platform",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index.js",
|
||||
@@ -142,7 +142,6 @@
|
||||
"@opentelemetry/sdk-trace-base": "^1.22.0",
|
||||
"@opentelemetry/sdk-trace-node": "^1.22.0",
|
||||
"@opentelemetry/semantic-conventions": "^1.22.0",
|
||||
"form-data-encoder": "^4.0.2",
|
||||
"humanize-duration": "^3.27.3",
|
||||
"socket.io-client": "4.7.4",
|
||||
"superjson": "^2.2.1",
|
||||
@@ -157,6 +156,7 @@
|
||||
"@types/humanize-duration": "^3.27.1",
|
||||
"@types/jest": "^29.5.3",
|
||||
"@types/node": "20.12.7",
|
||||
"@types/readable-stream": "^4.0.14",
|
||||
"jest": "^29.6.2",
|
||||
"rimraf": "^3.0.2",
|
||||
"socket.io": "4.7.4",
|
||||
|
||||
@@ -3,8 +3,7 @@ import { fromZodError } from "zod-validation-error";
|
||||
import { ApiConnectionError, ApiError } from "./errors";
|
||||
import { RetryOptions } from "../schemas";
|
||||
import { calculateNextRetryDelay } from "../utils/retries";
|
||||
import { FormDataEncoder } from "form-data-encoder";
|
||||
import { Readable } from "node:stream";
|
||||
|
||||
import {
|
||||
CursorPage,
|
||||
CursorPageParams,
|
||||
@@ -114,59 +113,6 @@ export function zodfetchOffsetLimitPage<TItemSchema extends z.ZodTypeAny>(
|
||||
return new OffsetLimitPagePromise(fetchResult, schema, url, params, requestInit, options);
|
||||
}
|
||||
|
||||
export function zodupload<
|
||||
TResponseBodySchema extends z.ZodTypeAny,
|
||||
TBody = Record<string, unknown>,
|
||||
>(
|
||||
schema: TResponseBodySchema,
|
||||
url: string,
|
||||
body: TBody,
|
||||
requestInit?: RequestInit,
|
||||
options?: ZodFetchOptions
|
||||
): ApiPromise<z.output<TResponseBodySchema>> {
|
||||
const finalRequestInit = createMultipartFormRequestInit(body, requestInit);
|
||||
|
||||
return new ApiPromise(_doZodFetch(schema, url, finalRequestInit, options));
|
||||
}
|
||||
|
||||
async function createMultipartFormRequestInit<TBody = Record<string, unknown>>(
|
||||
body: TBody,
|
||||
requestInit?: RequestInit
|
||||
): Promise<RequestInit> {
|
||||
const form = await createForm(body);
|
||||
const encoder = new FormDataEncoder(form);
|
||||
|
||||
const finalHeaders: Record<string, string> = {};
|
||||
|
||||
for (const [key, value] of Object.entries(requestInit?.headers || {})) {
|
||||
finalHeaders[key] = value as string;
|
||||
}
|
||||
|
||||
for (const [key, value] of Object.entries(encoder.headers)) {
|
||||
finalHeaders[key] = value;
|
||||
}
|
||||
|
||||
finalHeaders["Content-Length"] = String(encoder.contentLength);
|
||||
|
||||
const finalRequestInit: RequestInit = {
|
||||
...requestInit,
|
||||
headers: finalHeaders,
|
||||
body: Readable.from(encoder) as any,
|
||||
// @ts-expect-error
|
||||
duplex: "half",
|
||||
};
|
||||
|
||||
return finalRequestInit;
|
||||
}
|
||||
|
||||
const createForm = async <T = Record<string, unknown>>(body: T | undefined): Promise<FormData> => {
|
||||
const form = new FormData();
|
||||
await Promise.all(
|
||||
Object.entries(body || {}).map(([key, value]) => addFormValue(form, key, value))
|
||||
);
|
||||
return form;
|
||||
};
|
||||
|
||||
type ZodFetchResult<T> = {
|
||||
data: T;
|
||||
response: Response;
|
||||
@@ -324,214 +270,6 @@ function requestInitWithCache(requestInit?: RequestInit): RequestInit {
|
||||
}
|
||||
}
|
||||
|
||||
const addFormValue = async (form: FormData, key: string, value: unknown): Promise<void> => {
|
||||
if (value === undefined) return;
|
||||
if (value == null) {
|
||||
throw new TypeError(
|
||||
`Received null for "${key}"; to pass null in FormData, you must use the string 'null'`
|
||||
);
|
||||
}
|
||||
|
||||
// TODO: make nested formats configurable
|
||||
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
||||
form.append(key, String(value));
|
||||
} else if (
|
||||
isUploadable(value) ||
|
||||
isBlobLike(value) ||
|
||||
value instanceof Buffer ||
|
||||
value instanceof ArrayBuffer
|
||||
) {
|
||||
const file = await toFile(value);
|
||||
form.append(key, file as File);
|
||||
} else if (Array.isArray(value)) {
|
||||
await Promise.all(value.map((entry) => addFormValue(form, key + "[]", entry)));
|
||||
} else if (typeof value === "object") {
|
||||
await Promise.all(
|
||||
Object.entries(value).map(([name, prop]) => addFormValue(form, `${key}[${name}]`, prop))
|
||||
);
|
||||
} else {
|
||||
throw new TypeError(
|
||||
`Invalid value given to form, expected a string, number, boolean, object, Array, File or Blob but got ${value} instead`
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export type ToFileInput = Uploadable | Exclude<BlobLikePart, string> | AsyncIterable<BlobLikePart>;
|
||||
|
||||
/**
|
||||
* Helper for creating a {@link File} to pass to an SDK upload method from a variety of different data formats
|
||||
* @param value the raw content of the file. Can be an {@link Uploadable}, {@link BlobLikePart}, or {@link AsyncIterable} of {@link BlobLikePart}s
|
||||
* @param {string=} name the name of the file. If omitted, toFile will try to determine a file name from bits if possible
|
||||
* @param {Object=} options additional properties
|
||||
* @param {string=} options.type the MIME type of the content
|
||||
* @param {number=} options.lastModified the last modified timestamp
|
||||
* @returns a {@link File} with the given properties
|
||||
*/
|
||||
export async function toFile(
|
||||
value: ToFileInput | PromiseLike<ToFileInput>,
|
||||
name?: string | null | undefined,
|
||||
options?: FilePropertyBag | undefined
|
||||
): Promise<FileLike> {
|
||||
// If it's a promise, resolve it.
|
||||
value = await value;
|
||||
|
||||
// Use the file's options if there isn't one provided
|
||||
options ??= isFileLike(value) ? { lastModified: value.lastModified, type: value.type } : {};
|
||||
|
||||
if (isResponseLike(value)) {
|
||||
const blob = await value.blob();
|
||||
name ||= new URL(value.url).pathname.split(/[\\/]/).pop() ?? "unknown_file";
|
||||
|
||||
return new File([blob as any], name, options);
|
||||
}
|
||||
|
||||
const bits = await getBytes(value);
|
||||
|
||||
name ||= getName(value) ?? "unknown_file";
|
||||
|
||||
if (!options.type) {
|
||||
const type = (bits[0] as any)?.type;
|
||||
if (typeof type === "string") {
|
||||
options = { ...options, type };
|
||||
}
|
||||
}
|
||||
|
||||
return new File(bits, name, options);
|
||||
}
|
||||
|
||||
function getName(value: any): string | undefined {
|
||||
return (
|
||||
getStringFromMaybeBuffer(value.name) ||
|
||||
getStringFromMaybeBuffer(value.filename) ||
|
||||
// For fs.ReadStream
|
||||
getStringFromMaybeBuffer(value.path)?.split(/[\\/]/).pop()
|
||||
);
|
||||
}
|
||||
|
||||
const getStringFromMaybeBuffer = (x: string | Buffer | unknown): string | undefined => {
|
||||
if (typeof x === "string") return x;
|
||||
if (typeof Buffer !== "undefined" && x instanceof Buffer) return String(x);
|
||||
return undefined;
|
||||
};
|
||||
|
||||
async function getBytes(value: ToFileInput): Promise<Array<BlobPart>> {
|
||||
let parts: Array<BlobPart> = [];
|
||||
if (
|
||||
typeof value === "string" ||
|
||||
ArrayBuffer.isView(value) || // includes Uint8Array, Buffer, etc.
|
||||
value instanceof ArrayBuffer
|
||||
) {
|
||||
parts.push(value);
|
||||
} else if (isBlobLike(value)) {
|
||||
parts.push(await value.arrayBuffer());
|
||||
} else if (
|
||||
isAsyncIterableIterator(value) // includes Readable, ReadableStream, etc.
|
||||
) {
|
||||
for await (const chunk of value) {
|
||||
parts.push(chunk as BlobPart); // TODO, consider validating?
|
||||
}
|
||||
} else {
|
||||
throw new Error(
|
||||
`Unexpected data type: ${typeof value}; constructor: ${value?.constructor
|
||||
?.name}; props: ${propsForError(value)}`
|
||||
);
|
||||
}
|
||||
|
||||
return parts;
|
||||
}
|
||||
|
||||
function propsForError(value: any): string {
|
||||
const props = Object.getOwnPropertyNames(value);
|
||||
return `[${props.map((p) => `"${p}"`).join(", ")}]`;
|
||||
}
|
||||
|
||||
const isAsyncIterableIterator = (value: any): value is AsyncIterableIterator<unknown> =>
|
||||
value != null && typeof value === "object" && typeof value[Symbol.asyncIterator] === "function";
|
||||
|
||||
/**
|
||||
* Intended to match web.Blob, node.Blob, node-fetch.Blob, etc.
|
||||
*/
|
||||
export interface BlobLike {
|
||||
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Blob/size) */
|
||||
readonly size: number;
|
||||
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Blob/type) */
|
||||
readonly type: string;
|
||||
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Blob/text) */
|
||||
text(): Promise<string>;
|
||||
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Blob/slice) */
|
||||
slice(start?: number, end?: number): BlobLike;
|
||||
// unfortunately @types/node-fetch@^2.6.4 doesn't type the arrayBuffer method
|
||||
}
|
||||
|
||||
/**
|
||||
* Intended to match web.File, node.File, node-fetch.File, etc.
|
||||
*/
|
||||
export interface FileLike extends BlobLike {
|
||||
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/File/lastModified) */
|
||||
readonly lastModified: number;
|
||||
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/File/name) */
|
||||
readonly name: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Intended to match web.Response, node.Response, node-fetch.Response, etc.
|
||||
*/
|
||||
export interface ResponseLike {
|
||||
url: string;
|
||||
blob(): Promise<BlobLike>;
|
||||
}
|
||||
|
||||
export type Uploadable = FileLike | ResponseLike | Readable;
|
||||
|
||||
export const isResponseLike = (value: any): value is ResponseLike =>
|
||||
value != null &&
|
||||
typeof value === "object" &&
|
||||
typeof value.url === "string" &&
|
||||
typeof value.blob === "function";
|
||||
|
||||
export const isFileLike = (value: any): value is FileLike =>
|
||||
value != null &&
|
||||
typeof value === "object" &&
|
||||
typeof value.name === "string" &&
|
||||
typeof value.lastModified === "number" &&
|
||||
isBlobLike(value);
|
||||
|
||||
/**
|
||||
* The BlobLike type omits arrayBuffer() because @types/node-fetch@^2.6.4 lacks it; but this check
|
||||
* adds the arrayBuffer() method type because it is available and used at runtime
|
||||
*/
|
||||
export const isBlobLike = (
|
||||
value: any
|
||||
): value is BlobLike & { arrayBuffer(): Promise<ArrayBuffer> } =>
|
||||
value != null &&
|
||||
typeof value === "object" &&
|
||||
typeof value.size === "number" &&
|
||||
typeof value.type === "string" &&
|
||||
typeof value.text === "function" &&
|
||||
typeof value.slice === "function" &&
|
||||
typeof value.arrayBuffer === "function";
|
||||
|
||||
export const isFsReadStream = (value: any): value is Readable => value instanceof Readable;
|
||||
|
||||
export const isUploadable = (value: any): value is Uploadable => {
|
||||
return isFileLike(value) || isResponseLike(value) || isFsReadStream(value);
|
||||
};
|
||||
|
||||
export type BlobLikePart =
|
||||
| string
|
||||
| ArrayBuffer
|
||||
| ArrayBufferView
|
||||
| BlobLike
|
||||
| Uint8Array
|
||||
| DataView;
|
||||
|
||||
export const isRecordLike = (value: any): value is Record<string, string> =>
|
||||
value != null &&
|
||||
typeof value === "object" &&
|
||||
!Array.isArray(value) &&
|
||||
Object.keys(value).length > 0 &&
|
||||
Object.keys(value).every((key) => typeof key === "string" && typeof value[key] === "string");
|
||||
|
||||
/**
|
||||
* A subclass of `Promise` providing additional helper methods
|
||||
* for interacting with the SDK.
|
||||
|
||||
@@ -14,7 +14,6 @@ import {
|
||||
EnvironmentVariables,
|
||||
ListRunResponseItem,
|
||||
ListScheduleOptions,
|
||||
ListSchedulesResult,
|
||||
ReplayRunResponse,
|
||||
RetrieveRunResponse,
|
||||
ScheduleObject,
|
||||
@@ -28,11 +27,9 @@ import { taskContext } from "../task-context-api";
|
||||
import {
|
||||
CursorPagePromise,
|
||||
ZodFetchOptions,
|
||||
isRecordLike,
|
||||
zodfetch,
|
||||
zodfetchCursorPage,
|
||||
zodfetchOffsetLimitPage,
|
||||
zodupload,
|
||||
} from "./core";
|
||||
import { ApiError } from "./errors";
|
||||
import {
|
||||
@@ -331,27 +328,15 @@ export class ApiClient {
|
||||
}
|
||||
|
||||
importEnvVars(projectRef: string, slug: string, body: ImportEnvironmentVariablesParams) {
|
||||
if (isRecordLike(body.variables)) {
|
||||
return zodfetch(
|
||||
EnvironmentVariableResponseBody,
|
||||
`${this.baseUrl}/api/v1/projects/${projectRef}/envvars/${slug}/import`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: this.#getHeaders(false),
|
||||
body: JSON.stringify(body),
|
||||
}
|
||||
);
|
||||
} else {
|
||||
return zodupload(
|
||||
EnvironmentVariableResponseBody,
|
||||
`${this.baseUrl}/api/v1/projects/${projectRef}/envvars/${slug}/import`,
|
||||
body,
|
||||
{
|
||||
method: "POST",
|
||||
headers: this.#getHeaders(false),
|
||||
}
|
||||
);
|
||||
}
|
||||
return zodfetch(
|
||||
EnvironmentVariableResponseBody,
|
||||
`${this.baseUrl}/api/v1/projects/${projectRef}/envvars/${slug}/import`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: this.#getHeaders(false),
|
||||
body: JSON.stringify(body),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
retrieveEnvVar(projectRef: string, slug: string, key: string) {
|
||||
|
||||
@@ -1,18 +1,13 @@
|
||||
import { RunStatus } from "../schemas";
|
||||
import { BlobLikePart, Uploadable } from "./core";
|
||||
import { CursorPageParams } from "./pagination";
|
||||
|
||||
export interface ImportEnvironmentVariablesParams {
|
||||
/**
|
||||
* The variables to be imported. If a variable with the same key already exists, it will be overwritten when `override` is `true`.
|
||||
*
|
||||
* There are two ways to specify the variables:
|
||||
*
|
||||
* 1. As a record of key-value pairs. e.g. `{ "key1": "value1", "key2": "value2" }`
|
||||
* 2. As an "uploadable" object in dotenv format. An uploadable can be a Node readable stream, a string, or a Buffer. You can also pass the return value of a `fetch` call.
|
||||
* To specify the variables, you can pass them in as a record of key-value pairs. e.g. `{ "key1": "value1", "key2": "value2" }`
|
||||
*/
|
||||
variables: Uploadable | BlobLikePart | Record<string, string>;
|
||||
|
||||
variables: Record<string, string>;
|
||||
override?: boolean;
|
||||
}
|
||||
|
||||
|
||||
@@ -197,13 +197,11 @@ export class TracingSDK {
|
||||
}
|
||||
|
||||
public async flush() {
|
||||
await this._traceProvider.forceFlush();
|
||||
await this._logProvider.forceFlush();
|
||||
await Promise.all([this._traceProvider.forceFlush(), this._logProvider.forceFlush()]);
|
||||
}
|
||||
|
||||
public async shutdown() {
|
||||
await this._traceProvider.shutdown();
|
||||
await this._logProvider.shutdown();
|
||||
await Promise.all([this._traceProvider.shutdown(), this._logProvider.shutdown()]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -554,6 +554,10 @@ export const CoordinatorToPlatformMessages = {
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
callback: z.object({
|
||||
version: z.literal("v1").default("v1"),
|
||||
keepRunAlive: z.boolean(),
|
||||
}),
|
||||
},
|
||||
INDEXING_FAILED: {
|
||||
message: z.object({
|
||||
|
||||
@@ -17,5 +17,4 @@ export default defineConfig({
|
||||
"./src/v3/workers/index.ts",
|
||||
"./src/v3/zodfetch.ts",
|
||||
],
|
||||
external: ["node:stream"],
|
||||
});
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# @trigger.dev/eslint-plugin
|
||||
|
||||
## 3.0.0-beta.40
|
||||
|
||||
## 3.0.0-beta.39
|
||||
|
||||
## 3.0.0-beta.38
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/eslint-plugin",
|
||||
"version": "3.0.0-beta.39",
|
||||
"version": "3.0.0-beta.40",
|
||||
"description": "ESLint plugin with trigger.dev best practices",
|
||||
"keywords": [
|
||||
"eslint",
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# @trigger.dev/express
|
||||
|
||||
## 3.0.0-beta.40
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @trigger.dev/sdk@3.0.0-beta.40
|
||||
|
||||
## 3.0.0-beta.39
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/express",
|
||||
"version": "3.0.0-beta.39",
|
||||
"version": "3.0.0-beta.40",
|
||||
"description": "Official Express adapter for Trigger.dev",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index.js",
|
||||
@@ -23,7 +23,7 @@
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.39",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.40",
|
||||
"@trigger.dev/tsconfig": "workspace:*",
|
||||
"@types/debug": "^4.1.7",
|
||||
"@types/express": "^4.17.13",
|
||||
@@ -39,7 +39,7 @@
|
||||
"build:tsup": "tsup"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.39"
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.40"
|
||||
},
|
||||
"dependencies": {
|
||||
"debug": "^4.3.4",
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# @trigger.dev/hono
|
||||
|
||||
## 3.0.0-beta.40
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @trigger.dev/sdk@3.0.0-beta.40
|
||||
|
||||
## 3.0.0-beta.39
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/hono",
|
||||
"version": "3.0.0-beta.39",
|
||||
"version": "3.0.0-beta.40",
|
||||
"description": "A Trigger.dev adapter for Hono.dev",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index.js",
|
||||
@@ -32,7 +32,7 @@
|
||||
},
|
||||
"peerDependencies": {
|
||||
"hono": "3.x",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.39"
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.40"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@trigger.dev/tsconfig": "workspace:*",
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
# @trigger.dev/integration-kit
|
||||
|
||||
## 3.0.0-beta.40
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [55d1f8c67]
|
||||
- Updated dependencies [098932ea9]
|
||||
- Updated dependencies [9835f4ec5]
|
||||
- @trigger.dev/core@3.0.0-beta.40
|
||||
|
||||
## 3.0.0-beta.39
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/integration-kit",
|
||||
"version": "3.0.0-beta.39",
|
||||
"version": "3.0.0-beta.40",
|
||||
"description": "Trigger.dev Integration Kit has helpers to make creating integrations easier",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index.js",
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# @trigger.dev/nestjs
|
||||
|
||||
## 3.0.0-beta.40
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @trigger.dev/sdk@3.0.0-beta.40
|
||||
|
||||
## 3.0.0-beta.39
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/nestjs",
|
||||
"version": "3.0.0-beta.39",
|
||||
"version": "3.0.0-beta.40",
|
||||
"description": "Official NestJS adapter for Trigger.dev",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index.js",
|
||||
@@ -23,7 +23,7 @@
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.39",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.40",
|
||||
"@trigger.dev/tsconfig": "workspace:*",
|
||||
"@types/debug": "^4.1.7",
|
||||
"@types/express": "^4.17.13",
|
||||
@@ -41,7 +41,7 @@
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@nestjs/common": ">=10.0.0",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.39"
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.40"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nestjs/common": "^10.2.4",
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# @trigger.dev/nextjs
|
||||
|
||||
## 3.0.0-beta.40
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @trigger.dev/sdk@3.0.0-beta.40
|
||||
|
||||
## 3.0.0-beta.39
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/nextjs",
|
||||
"version": "3.0.0-beta.39",
|
||||
"version": "3.0.0-beta.40",
|
||||
"description": "Trigger.dev Next.js integration",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index.js",
|
||||
@@ -41,7 +41,7 @@
|
||||
"build:tsup": "tsup"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.39",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.40",
|
||||
"next": ">=12.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# @trigger.dev/otlp-importer
|
||||
|
||||
## 3.0.0-beta.40
|
||||
|
||||
## 3.0.0-beta.39
|
||||
|
||||
## 3.0.0-beta.38
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/otlp-importer",
|
||||
"version": "3.0.0-beta.39",
|
||||
"version": "3.0.0-beta.40",
|
||||
"description": "OpenTelemetry OTLP Importer for Node.js written in TypeScript",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index.js",
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
# @trigger.dev/react
|
||||
|
||||
## 3.0.0-beta.40
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [55d1f8c67]
|
||||
- Updated dependencies [098932ea9]
|
||||
- Updated dependencies [9835f4ec5]
|
||||
- @trigger.dev/core@3.0.0-beta.40
|
||||
|
||||
## 3.0.0-beta.39
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/react",
|
||||
"version": "3.0.0-beta.39",
|
||||
"version": "3.0.0-beta.40",
|
||||
"description": "Trigger.dev React SDK",
|
||||
"license": "MIT",
|
||||
"types": "dist/index.d.ts",
|
||||
@@ -27,7 +27,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@tanstack/react-query": "5.0.0-beta.2",
|
||||
"@trigger.dev/core": "workspace:^3.0.0-beta.39",
|
||||
"@trigger.dev/core": "workspace:^3.0.0-beta.40",
|
||||
"debug": "^4.3.4",
|
||||
"zod": "3.22.3"
|
||||
},
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# @trigger.dev/remix
|
||||
|
||||
## 3.0.0-beta.40
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @trigger.dev/sdk@3.0.0-beta.40
|
||||
|
||||
## 3.0.0-beta.39
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/remix",
|
||||
"version": "3.0.0-beta.39",
|
||||
"version": "3.0.0-beta.40",
|
||||
"description": "Trigger.dev Remix integration",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index.js",
|
||||
@@ -39,7 +39,7 @@
|
||||
"build:tsup": "tsup"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.39",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.40",
|
||||
"@remix-run/server-runtime": ">1.19.0"
|
||||
},
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# @trigger.dev/sveltekit
|
||||
|
||||
## 3.0.0-beta.40
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @trigger.dev/sdk@3.0.0-beta.40
|
||||
|
||||
## 3.0.0-beta.39
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/sveltekit",
|
||||
"version": "3.0.0-beta.39",
|
||||
"version": "3.0.0-beta.40",
|
||||
"description": "Trigger.dev svelteKit integration",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index.js",
|
||||
@@ -39,7 +39,7 @@
|
||||
"build:tsup": "tsup"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.39"
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.40"
|
||||
},
|
||||
"dependencies": {
|
||||
"debug": "^4.3.4"
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
# @trigger.dev/testing
|
||||
|
||||
## 3.0.0-beta.40
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [55d1f8c67]
|
||||
- Updated dependencies [098932ea9]
|
||||
- Updated dependencies [9835f4ec5]
|
||||
- @trigger.dev/core@3.0.0-beta.40
|
||||
- @trigger.dev/sdk@3.0.0-beta.40
|
||||
|
||||
## 3.0.0-beta.39
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@trigger.dev/testing",
|
||||
"description": "A collection of useful tools to write tests for Trigger.dev.",
|
||||
"version": "3.0.0-beta.39",
|
||||
"version": "3.0.0-beta.40",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
# @trigger.dev/sdk
|
||||
|
||||
## 3.0.0-beta.40
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [55d1f8c67]
|
||||
- Updated dependencies [098932ea9]
|
||||
- Updated dependencies [9835f4ec5]
|
||||
- @trigger.dev/core@3.0.0-beta.40
|
||||
- @trigger.dev/core-backend@3.0.0-beta.40
|
||||
|
||||
## 3.0.0-beta.39
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/sdk",
|
||||
"version": "3.0.0-beta.39",
|
||||
"version": "3.0.0-beta.40",
|
||||
"description": "trigger.dev Node.JS SDK",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index.js",
|
||||
@@ -48,8 +48,8 @@
|
||||
"@opentelemetry/api": "^1.8.0",
|
||||
"@opentelemetry/api-logs": "^0.48.0",
|
||||
"@opentelemetry/semantic-conventions": "^1.22.0",
|
||||
"@trigger.dev/core": "workspace:3.0.0-beta.39",
|
||||
"@trigger.dev/core-backend": "workspace:3.0.0-beta.39",
|
||||
"@trigger.dev/core": "workspace:3.0.0-beta.40",
|
||||
"@trigger.dev/core-backend": "workspace:3.0.0-beta.40",
|
||||
"chalk": "^5.2.0",
|
||||
"cronstrue": "^2.21.0",
|
||||
"debug": "^4.3.4",
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user