50e3d9e43a
* Added EndpointIndex status. Default is PENDING, existing rows are SUCCESS * Made it easier to create a migration SQL file * Created a job-catalog file for misconfigured Jobs that should error when running the CLI * EndpointIndex data and state are now optional * The Environments page now shows the status of the last refresh * Improved the UI about endpoints * Added EndpointIndex error column * WIP making the endpoint indexing more robust * Indexing errors are now surfaced * Improved the error show it shows the job id * Use “performEndpointIndexing” when you create your first endpoint from the UI * Use “performEndpointIndexing” for the recurring endpoint checker * Staging is now auto-indexed every 10 mins too * Use “performEndpointIndexing” for the webhook * Moved the throttling to a util * Removed instructional comments * Created a reusable retry system with exponential backoff * Use p-retry for retrying with backoff * The CLI gets indexing results and displays errors * Improved the indexing error messages and display in the console * Use a pre so the Indexing error is correctly split over multiple lines * Use a db transaction for webhook that triggers endpoint indexing * Tidied up imports * Support older versions of the server * Improved the comment on the misconfigured job * Changeset: When indexing user's jobs errors are now stored and displayed
114 lines
3.4 KiB
TypeScript
114 lines
3.4 KiB
TypeScript
import { customAlphabet } from "nanoid";
|
|
import { $transaction, prisma, PrismaClient } from "~/db.server";
|
|
import { env } from "~/env.server";
|
|
import { AuthenticatedEnvironment } from "../apiAuth.server";
|
|
import { workerQueue } from "../worker.server";
|
|
import { CreateEndpointError } from "./createEndpoint.server";
|
|
import { EndpointApi } from "../endpointApi.server";
|
|
import { RuntimeEnvironmentType } from "@trigger.dev/database";
|
|
|
|
const indexingHookIdentifier = customAlphabet("0123456789abcdefghijklmnopqrstuvxyz", 10);
|
|
|
|
export class ValidateCreateEndpointService {
|
|
#prismaClient: PrismaClient;
|
|
|
|
constructor(prismaClient: PrismaClient = prisma) {
|
|
this.#prismaClient = prismaClient;
|
|
}
|
|
|
|
public async call({ environment, url }: { environment: AuthenticatedEnvironment; url: string }) {
|
|
const endpointUrl = this.#normalizeEndpointUrl(url);
|
|
|
|
const client = new EndpointApi(environment.apiKey, endpointUrl);
|
|
|
|
const validationResult = await client.validate();
|
|
|
|
if (!validationResult.ok) {
|
|
throw new Error(validationResult.error);
|
|
}
|
|
|
|
try {
|
|
const result = await $transaction(this.#prismaClient, async (tx) => {
|
|
const endpoint = await tx.endpoint.upsert({
|
|
where: {
|
|
environmentId_slug: {
|
|
environmentId: environment.id,
|
|
slug: validationResult.endpointId,
|
|
},
|
|
},
|
|
include: {
|
|
environment: true,
|
|
},
|
|
create: {
|
|
environment: {
|
|
connect: {
|
|
id: environment.id,
|
|
},
|
|
},
|
|
organization: {
|
|
connect: {
|
|
id: environment.organizationId,
|
|
},
|
|
},
|
|
project: {
|
|
connect: {
|
|
id: environment.projectId,
|
|
},
|
|
},
|
|
slug: validationResult.endpointId,
|
|
url: endpointUrl,
|
|
indexingHookIdentifier: indexingHookIdentifier(),
|
|
version: validationResult.triggerVersion,
|
|
},
|
|
update: {
|
|
url: endpointUrl,
|
|
version: validationResult.triggerVersion,
|
|
},
|
|
});
|
|
|
|
const index = await tx.endpointIndex.create({
|
|
data: { endpointId: endpoint.id, status: "PENDING", source: "INTERNAL" },
|
|
});
|
|
|
|
// Kick off process to fetch the jobs for this index
|
|
await workerQueue.enqueue(
|
|
"performEndpointIndexing",
|
|
{
|
|
id: index.id,
|
|
},
|
|
{
|
|
tx,
|
|
maxAttempts:
|
|
endpoint.environment.type === RuntimeEnvironmentType.DEVELOPMENT ? 1 : undefined,
|
|
}
|
|
);
|
|
|
|
return endpoint;
|
|
});
|
|
|
|
return result;
|
|
} catch (error) {
|
|
if (error instanceof Error) {
|
|
throw new CreateEndpointError("FAILED_UPSERT", error.message);
|
|
} else {
|
|
throw new CreateEndpointError("FAILED_UPSERT", "Something went wrong");
|
|
}
|
|
}
|
|
}
|
|
|
|
// If the endpoint URL points to localhost, and the RUNTIME_PLATFORM is docker-compose, then we need to rewrite the host to host.docker.internal
|
|
// otherwise we shouldn't change anything
|
|
#normalizeEndpointUrl(url: string) {
|
|
if (env.RUNTIME_PLATFORM === "docker-compose") {
|
|
const urlObj = new URL(url);
|
|
|
|
if (urlObj.hostname === "localhost") {
|
|
urlObj.hostname = "host.docker.internal";
|
|
return urlObj.toString();
|
|
}
|
|
}
|
|
|
|
return url;
|
|
}
|
|
}
|