chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
import { logger, type RuntimeEnvironmentType } from "@trigger.dev/core/v3";
|
||||
import { type RunEngineVersion } from "@trigger.dev/database";
|
||||
import { ServiceValidationError } from "~/v3/services/baseService.server";
|
||||
import { BasePresenter } from "./basePresenter.server";
|
||||
import { waitpointStatusToApiStatus } from "./WaitpointListPresenter.server";
|
||||
import { generateHttpCallbackUrl } from "~/services/httpCallback.server";
|
||||
import type { PrismaClientOrTransaction, PrismaReplicaClient } from "~/db.server";
|
||||
import { readThroughRun } from "~/v3/runOpsMigration/readThrough.server";
|
||||
|
||||
// When omitted, clients default to the inherited _replica handle => passthrough reads the
|
||||
// replica exactly as today. isPastRetention is injectable for tests. Typed PrismaReplicaClient
|
||||
// to match readThroughRun's readNew/readLegacy + deps.
|
||||
type ApiWaitpointPresenterReadThroughDeps = {
|
||||
newClient?: PrismaReplicaClient;
|
||||
legacyReplica?: PrismaReplicaClient;
|
||||
splitEnabled?: boolean;
|
||||
isPastRetention?: (id: string) => boolean;
|
||||
};
|
||||
|
||||
export class ApiWaitpointPresenter extends BasePresenter {
|
||||
constructor(
|
||||
prismaClient?: PrismaClientOrTransaction,
|
||||
replicaClient?: PrismaClientOrTransaction,
|
||||
private readonly readThroughDeps?: ApiWaitpointPresenterReadThroughDeps
|
||||
) {
|
||||
super(prismaClient, replicaClient);
|
||||
}
|
||||
|
||||
public async call(
|
||||
environment: {
|
||||
id: string;
|
||||
type: RuntimeEnvironmentType;
|
||||
project: {
|
||||
id: string;
|
||||
engine: RunEngineVersion;
|
||||
};
|
||||
apiKey: string;
|
||||
},
|
||||
waitpointId: string
|
||||
) {
|
||||
return this.trace("call", async (span) => {
|
||||
// Public waitpoint retrieve. Split on: new run-ops client first, then the LEGACY
|
||||
// RUN-OPS READ REPLICA ONLY on a new-probe miss — never the legacy primary.
|
||||
// Split off (single-DB / self-host): one plain waitpoint.findFirst against the replica
|
||||
// (passthrough). The waitpointId is the residency-classifiable run-ops id (the route
|
||||
// pre-decodes the friendlyId via WaitpointId.toId).
|
||||
const hydrate = (client: PrismaReplicaClient) =>
|
||||
client.waitpoint.findFirst({
|
||||
where: {
|
||||
id: waitpointId,
|
||||
environmentId: environment.id,
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
friendlyId: true,
|
||||
type: true,
|
||||
status: true,
|
||||
idempotencyKey: true,
|
||||
userProvidedIdempotencyKey: true,
|
||||
idempotencyKeyExpiresAt: true,
|
||||
inactiveIdempotencyKey: true,
|
||||
output: true,
|
||||
outputType: true,
|
||||
outputIsError: true,
|
||||
completedAfter: true,
|
||||
completedAt: true,
|
||||
createdAt: true,
|
||||
tags: true,
|
||||
},
|
||||
});
|
||||
|
||||
const result = await readThroughRun({
|
||||
runId: waitpointId,
|
||||
environmentId: environment.id,
|
||||
readNew: (client) => hydrate(client),
|
||||
readLegacy: (replica) => hydrate(replica),
|
||||
deps: {
|
||||
splitEnabled: this.readThroughDeps?.splitEnabled,
|
||||
// Default both clients to the inherited _replica handle (declared
|
||||
// PrismaClientOrTransaction but $replica at runtime) so passthrough reads the replica
|
||||
// as today; split mode injects a distinct newClient.
|
||||
newClient: this.readThroughDeps?.newClient ?? (this._replica as PrismaReplicaClient),
|
||||
legacyReplica:
|
||||
this.readThroughDeps?.legacyReplica ?? (this._replica as PrismaReplicaClient),
|
||||
isPastRetention: this.readThroughDeps?.isPastRetention,
|
||||
},
|
||||
});
|
||||
|
||||
const waitpoint =
|
||||
result.source === "new" || result.source === "legacy-replica" ? result.value : null;
|
||||
|
||||
if (!waitpoint) {
|
||||
logger.error(`WaitpointPresenter: Waitpoint not found`, {
|
||||
id: waitpointId,
|
||||
});
|
||||
throw new ServiceValidationError("Waitpoint not found");
|
||||
}
|
||||
|
||||
let _isTimeout = false;
|
||||
if (waitpoint.outputIsError && waitpoint.output) {
|
||||
_isTimeout = true;
|
||||
}
|
||||
|
||||
return {
|
||||
id: waitpoint.friendlyId,
|
||||
type: waitpoint.type,
|
||||
url: generateHttpCallbackUrl(waitpoint.id, environment.apiKey),
|
||||
status: waitpointStatusToApiStatus(waitpoint.status, waitpoint.outputIsError),
|
||||
idempotencyKey: waitpoint.idempotencyKey,
|
||||
userProvidedIdempotencyKey: waitpoint.userProvidedIdempotencyKey,
|
||||
idempotencyKeyExpiresAt: waitpoint.idempotencyKeyExpiresAt ?? undefined,
|
||||
inactiveIdempotencyKey: waitpoint.inactiveIdempotencyKey ?? undefined,
|
||||
output: waitpoint.output ?? undefined,
|
||||
outputType: waitpoint.outputType,
|
||||
outputIsError: waitpoint.outputIsError,
|
||||
timeoutAt: waitpoint.completedAfter ?? undefined,
|
||||
completedAfter: waitpoint.completedAfter ?? undefined,
|
||||
completedAt: waitpoint.completedAt ?? undefined,
|
||||
createdAt: waitpoint.createdAt,
|
||||
tags: waitpoint.tags,
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user