Removed ts in favor of ulid’s, and starting to implement the task list api #117
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import type { ActionArgs } from "@remix-run/server-runtime";
|
||||
import type { ActionArgs, LoaderArgs } from "@remix-run/server-runtime";
|
||||
import { json } from "@remix-run/server-runtime";
|
||||
import type { RunTaskBodyOutput } from "@trigger.dev/internal";
|
||||
import { RunTaskBodyOutputSchema } from "@trigger.dev/internal";
|
||||
@@ -7,6 +7,7 @@ import type { PrismaClient } from "~/db.server";
|
||||
import { prisma } from "~/db.server";
|
||||
import { authenticateApiRequest } from "~/services/apiAuth.server";
|
||||
import { logger } from "~/services/logger";
|
||||
import { ulid } from "~/services/ulid.server";
|
||||
|
||||
const ParamsSchema = z.object({
|
||||
executionId: z.string(),
|
||||
@@ -16,6 +17,61 @@ const HeadersSchema = z.object({
|
||||
"idempotency-key": z.string(),
|
||||
});
|
||||
|
||||
const SearchQuerySchema = z.object({
|
||||
cursor: z.string().optional(),
|
||||
take: z.coerce.number().default(50),
|
||||
});
|
||||
|
||||
export async function loader({ request, params }: LoaderArgs) {
|
||||
// Next authenticate the request
|
||||
const authenticatedEnv = await authenticateApiRequest(request);
|
||||
|
||||
if (!authenticatedEnv) {
|
||||
return json({ error: "Invalid or Missing API key" }, { status: 401 });
|
||||
}
|
||||
|
||||
const { executionId } = ParamsSchema.parse(params);
|
||||
|
||||
const url = new URL(request.url);
|
||||
const query = SearchQuerySchema.parse(Object.fromEntries(url.searchParams));
|
||||
|
||||
const execution = await prisma.execution.findUnique({
|
||||
where: {
|
||||
id: executionId,
|
||||
},
|
||||
include: {
|
||||
tasks: {
|
||||
orderBy: {
|
||||
id: "asc",
|
||||
},
|
||||
take: query.take,
|
||||
skip: query.cursor ? 1 : 0,
|
||||
cursor: query.cursor
|
||||
? {
|
||||
id: query.cursor,
|
||||
}
|
||||
: undefined,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (!execution) {
|
||||
return json({ error: "Execution not found" }, { status: 404 });
|
||||
}
|
||||
|
||||
if (execution.environmentId !== authenticatedEnv.id) {
|
||||
return json({ error: "Execution not found" }, { status: 404 });
|
||||
}
|
||||
|
||||
return json({
|
||||
data: execution.tasks,
|
||||
nextCursor:
|
||||
execution.tasks.length > 0
|
||||
? execution.tasks[execution.tasks.length - 1]?.id
|
||||
: undefined,
|
||||
});
|
||||
}
|
||||
|
||||
export async function action({ request, params }: ActionArgs) {
|
||||
// Ensure this is a POST request
|
||||
if (request.method.toUpperCase() !== "POST") {
|
||||
@@ -116,6 +172,7 @@ export class RunExecutionTaskService {
|
||||
|
||||
const task = await prisma.task.create({
|
||||
data: {
|
||||
id: ulid(),
|
||||
idempotencyKey,
|
||||
execution: {
|
||||
connect: {
|
||||
@@ -125,7 +182,8 @@ export class RunExecutionTaskService {
|
||||
name: taskBody.name,
|
||||
description: taskBody.description,
|
||||
status,
|
||||
ts: taskBody.ts,
|
||||
startedAt: new Date(),
|
||||
completedAt: status === "COMPLETED" ? new Date() : undefined,
|
||||
noop: taskBody.noop,
|
||||
delayUntil: taskBody.delayUntil,
|
||||
params: taskBody.params ?? undefined,
|
||||
|
||||
@@ -46,6 +46,7 @@ export class ResumeTaskService {
|
||||
},
|
||||
data: {
|
||||
status: task.noop ? "COMPLETED" : "RUNNING",
|
||||
completedAt: task.noop ? new Date() : undefined,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import { monotonicFactory } from "ulid";
|
||||
|
||||
const factory = monotonicFactory();
|
||||
|
||||
export function ulid(): ReturnType<typeof factory> {
|
||||
return factory().toLowerCase();
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
/*
|
||||
Warnings:
|
||||
|
||||
- You are about to drop the column `ts` on the `Task` table. All the data in the column will be lost.
|
||||
|
||||
*/
|
||||
-- AlterTable
|
||||
ALTER TABLE "Task" DROP COLUMN "ts";
|
||||
@@ -992,10 +992,9 @@ enum ExecutionStatus {
|
||||
}
|
||||
|
||||
model Task {
|
||||
id String @id @default(cuid())
|
||||
id String @id
|
||||
idempotencyKey String
|
||||
name String
|
||||
ts String
|
||||
|
||||
status TaskStatus @default(PENDING)
|
||||
delayUntil DateTime?
|
||||
|
||||
@@ -127,7 +127,6 @@ export type CachedTask = z.infer<typeof CachedTaskSchema>;
|
||||
|
||||
export const IOTaskSchema = z.object({
|
||||
name: z.string(),
|
||||
ts: z.string().default(() => String(Date.now())),
|
||||
noop: z.boolean().default(false),
|
||||
delayUntil: z.coerce.date().optional(),
|
||||
description: z.string().optional(),
|
||||
|
||||
@@ -21,7 +21,6 @@ export type TaskStatus = z.infer<typeof TaskStatusSchema>;
|
||||
export const TaskSchema = z.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
ts: z.string(),
|
||||
noop: z.boolean().default(false),
|
||||
startedAt: z.coerce.date().optional().nullable(),
|
||||
completedAt: z.coerce.date().optional().nullable(),
|
||||
@@ -49,7 +48,6 @@ export const ServerTaskSchema = TaskSchema.extend({
|
||||
export const CachedTaskSchema = z.object({
|
||||
id: z.string(),
|
||||
idempotencyKey: z.string(),
|
||||
ts: z.string(),
|
||||
status: TaskStatusSchema,
|
||||
noop: z.boolean().default(false),
|
||||
output: DeserializedJsonSchema.optional().nullable(),
|
||||
|
||||
@@ -63,7 +63,6 @@ export class IO {
|
||||
idempotencyKey,
|
||||
noop: false,
|
||||
...options,
|
||||
ts: options.ts ?? String(Date.now()),
|
||||
});
|
||||
|
||||
if (task.status === "COMPLETED") {
|
||||
|
||||
Reference in New Issue
Block a user