1- import { and , desc , eq , gt , inArray , isNotNull , isNull , ne , or , sql } from "drizzle-orm" ;
1+ import { and , desc , eq , inArray , isNotNull , isNull , sql } from "drizzle-orm" ;
22import { schema , type DB , type ResolvedSenderPrincipal , type WorkflowRunLaunchSpecStore } from "@intx/db" ;
33import { MAIL_ADMISSION_DENIED_CODE } from "@intx/hub-sessions" ;
44import type { RunTriggerMaterialize } from "@corbits/webhooks" ;
@@ -50,12 +50,8 @@ export function systemSenderMaterializer(materialize: RunTriggerMaterialize, sen
5050 } ;
5151}
5252
53- /**
54- * `cancelling` once cancellation was requested: the run stays live until the lifecycle sweep stops it. `workflowVersion`
55- * once read from its launch spec, for one pinned from the package registry; `offeringId`, the decision-model offering
56- * the deployment resolved, once read from its launch spec.
57- */
58- export type LiveDeployment = { runId : string ; address : string ; createdAt : Date ; cancelling : boolean ; endedAt ?: Date ; workflowVersion ?: string ; offeringId ?: string } ;
53+ /** `cancelling` once cancellation was requested: the run stays live until the lifecycle sweep stops it. */
54+ export type LiveDeployment = { runId : string ; address : string ; createdAt : Date ; cancelling : boolean } ;
5955
6056export type TenantDeployment = LiveDeployment & { workflow : string } ;
6157
@@ -72,26 +68,24 @@ function markedAs(kind: DeploymentKind) {
7268 return kind === "worker" ? eq ( marker , "true" ) : isNull ( marker ) ;
7369}
7470
75- type DeploymentQuery = { tenantId : string ; definitionName ?: string ; kind : DeploymentKind ; endedSince ?: Date } ;
71+ type DeploymentQuery = { tenantId : string ; definitionName ?: string ; kind : DeploymentKind } ;
7672
7773/**
7874 * A workflow the portal publishes per person deploys from an asset named for its publisher and release, which names
7975 * its definition too; its frozen projection keeps the workflow's own id, so that is the name a deployment is found by.
8076 */
8177export const workflowName = sql < string > `coalesce(${ schema . workflowRunLaunchSpec . frozenApprovalBundle } -> 'projection' ->> 'id', ${ schema . workflowDefinition . name } )` ;
8278
83- /** Matches how the hub lists deployments: a deployment is its anchor run. Newest first; live, or ended since `endedSince` . */
79+ /** Matches how the hub lists deployments: a deployment is its anchor run. Newest first, live only . */
8480async function deploymentsWhere ( db : DB [ "db" ] , query : DeploymentQuery ) : Promise < TenantDeployment [ ] > {
8581 const { workflowRun, workflowDefinition, workflowRunLaunchSpec, tenant, liveWorkflowRunStatuses } = schema ;
86- const live = inArray ( workflowRun . status , [ ...liveWorkflowRunStatuses ] ) ;
8782 const rows = await db
8883 . select ( {
8984 runId : workflowRun . id ,
9085 workflow : workflowName ,
9186 domain : tenant . domain ,
9287 createdAt : workflowRun . createdAt ,
9388 cancellationRequestedAt : workflowRun . cancellationRequestedAt ,
94- endedAt : workflowRun . endedAt ,
9589 } )
9690 . from ( workflowRun )
9791 . innerJoin ( workflowDefinition , eq ( workflowRun . definitionId , workflowDefinition . id ) )
@@ -102,7 +96,7 @@ async function deploymentsWhere(db: DB["db"], query: DeploymentQuery): Promise<T
10296 query . definitionName === undefined ? undefined : eq ( workflowName , query . definitionName ) ,
10397 isNotNull ( workflowRun . anchorRunId ) ,
10498 eq ( workflowRun . id , workflowRun . anchorRunId ) ,
105- query . endedSince === undefined ? live : or ( live , gt ( workflowRun . endedAt , query . endedSince ) ) ,
99+ inArray ( workflowRun . status , [ ... liveWorkflowRunStatuses ] ) ,
106100 markedAs ( query . kind ) ,
107101 ) )
108102 . orderBy ( desc ( workflowRun . createdAt ) , desc ( workflowRun . id ) ) ;
@@ -111,7 +105,6 @@ async function deploymentsWhere(db: DB["db"], query: DeploymentQuery): Promise<T
111105 address : `${ row . runId } @${ row . domain } ` ,
112106 createdAt : row . createdAt ,
113107 cancelling : row . cancellationRequestedAt !== null ,
114- ...( row . endedAt !== null && { endedAt : row . endedAt } ) ,
115108 workflow : row . workflow ,
116109 } ) ) ;
117110}
@@ -121,34 +114,6 @@ export function resolveLiveDeployments(db: DB["db"], tenantId: string, definitio
121114 return deploymentsWhere ( db , { tenantId, definitionName, kind } ) ;
122115}
123116
124- /** Workers live or released since `endedSince`: a worker's one body run landed in its log before its anchor was cancelled, so the log outlives the deployment. */
125- export function recentWorkers ( db : DB [ "db" ] , tenantId : string , definitionName : string , endedSince : Date ) : Promise < TenantDeployment [ ] > {
126- return deploymentsWhere ( db , { tenantId, definitionName, kind : "worker" , endedSince } ) ;
127- }
128-
129- export type ActiveTenant = { id : string ; domain : string } ;
130-
131- /**
132- * Tenants with a child run of the definition in flight, or ended or created since `endedSince`: a run inserted already
133- * completed, as a Bitbucket run is, keeps a null `endedAt` (stock leaves a terminal run routable that way), so its
134- * creation time is what says it just ended, and its verdict is recorded within a pass.
135- */
136- export async function activeTenants ( db : DB [ "db" ] , definitionName : string , what : "runs" | "deployments" , endedSince ?: Date ) : Promise < ActiveTenant [ ] > {
137- const { workflowRun, workflowDefinition, tenant, liveWorkflowRunStatuses } = schema ;
138- const running = eq ( workflowRun . status , "running" ) ;
139- const childRuns = endedSince === undefined ? running : or ( running , gt ( workflowRun . endedAt , endedSince ) , gt ( workflowRun . createdAt , endedSince ) ) ;
140- return db
141- . selectDistinct ( { id : tenant . id , domain : tenant . domain } )
142- . from ( workflowRun )
143- . innerJoin ( workflowDefinition , eq ( workflowRun . definitionId , workflowDefinition . id ) )
144- . innerJoin ( tenant , eq ( workflowRun . tenantId , tenant . id ) )
145- . where ( and (
146- eq ( workflowDefinition . name , definitionName ) ,
147- what === "runs" ? ne ( workflowRun . id , workflowRun . anchorRunId ) : eq ( workflowRun . id , workflowRun . anchorRunId ) ,
148- what === "runs" ? childRuns : inArray ( workflowRun . status , [ ...liveWorkflowRunStatuses ] ) ,
149- ) ) ;
150- }
151-
152117export function newestLive ( deployments : readonly LiveDeployment [ ] ) : LiveDeployment | undefined {
153118 return deployments . find ( ( live ) => ! live . cancelling ) ;
154119}
@@ -201,20 +166,6 @@ function pinFor(bundle: FrozenApprovalBundle): string | undefined {
201166 return pinOf ( bundle . closure ) ;
202167}
203168
204- export async function withWorkflowVersions < T extends LiveDeployment > (
205- launchSpecs : Pick < WorkflowRunLaunchSpecStore , "get" > ,
206- deployments : readonly T [ ] ,
207- ) : Promise < T [ ] > {
208- const versioned : T [ ] = [ ] ;
209- for ( const deployment of deployments ) {
210- const spec = await launchSpecs . get ( deployment . runId ) ;
211- const workflowVersion = spec ? closureVersions ( spec . frozenApprovalBundle ) ?. workflow . version : undefined ;
212- const offeringId = spec ?. defaultSourceOfferingId ?? undefined ;
213- versioned . push ( { ...deployment , ...( workflowVersion !== undefined && { workflowVersion } ) , ...( offeringId !== undefined && { offeringId } ) } ) ;
214- }
215- return versioned ;
216- }
217-
218169/** The reason the hub gave when it replaced a busy deployment with a fresh copy, which earlier audit entries carry. */
219170export const ROTATION_REASON = "Replaced by a fresh deployment of the same workflow" ;
220171
0 commit comments