@@ -23,7 +23,7 @@ import {
2323 resolveActiveWorkspaceApplicationContext ,
2424} from '@/lib/workspaces/application/context'
2525
26- const CHILD_SNAPSHOT_QUERY_CHUNK_SIZE = 1_000
26+ const SNAPSHOT_QUERY_CHUNK_SIZE = 1_000
2727
2828interface WorkflowExecutionRecord {
2929 kind : 'workflow'
@@ -37,7 +37,6 @@ interface WorkflowExecutionRecord {
3737 endedAt : Date | null
3838 totalDurationMs : number | null
3939 costTotal : string | null
40- executionData : unknown
4140}
4241
4342interface JobExecutionRecord {
@@ -79,7 +78,6 @@ async function resolveExecutionSnapshotContext(
7978 endedAt : workflowExecutionLogs . endedAt ,
8079 totalDurationMs : workflowExecutionLogs . totalDurationMs ,
8180 costTotal : workflowExecutionLogs . costTotal ,
82- executionData : workflowExecutionLogs . executionData ,
8381 } )
8482 . from ( workflowExecutionLogs )
8583 . where ( eq ( workflowExecutionLogs . executionId , executionId ) )
@@ -118,6 +116,40 @@ async function resolveExecutionSnapshotContext(
118116 return { ...workspace , executionId, record : { kind : 'job' , ...jobRecord } }
119117}
120118
119+ async function readSnapshotStates (
120+ ids : string [ ] ,
121+ signal : AbortSignal | undefined
122+ ) : Promise < Map < string , unknown > > {
123+ const states = new Map < string , unknown > ( )
124+ for ( let index = 0 ; index < ids . length ; index += SNAPSHOT_QUERY_CHUNK_SIZE ) {
125+ signal ?. throwIfAborted ( )
126+ const rows = await db
127+ . select ( {
128+ id : workflowExecutionSnapshots . id ,
129+ stateData : workflowExecutionSnapshots . stateData ,
130+ } )
131+ . from ( workflowExecutionSnapshots )
132+ . where (
133+ inArray ( workflowExecutionSnapshots . id , ids . slice ( index , index + SNAPSHOT_QUERY_CHUNK_SIZE ) )
134+ )
135+ for ( const row of rows ) states . set ( row . id , row . stateData )
136+ }
137+ return states
138+ }
139+
140+ /**
141+ * Read here, after authorization, rather than with the context: a caller the
142+ * use case refuses never fetches the run's execution data.
143+ */
144+ async function readExecutionData ( executionId : string ) : Promise < unknown > {
145+ const [ row ] = await db
146+ . select ( { executionData : workflowExecutionLogs . executionData } )
147+ . from ( workflowExecutionLogs )
148+ . where ( eq ( workflowExecutionLogs . executionId , executionId ) )
149+ . limit ( 1 )
150+ return row ?. executionData ?? null
151+ }
152+
121153function collectChildSnapshotIds ( traceSpans : TraceSpan [ ] ) : string [ ] {
122154 const ids = new Set < string > ( )
123155 const pending = [ ...traceSpans ]
@@ -175,17 +207,16 @@ const authorizedReadExecutionSnapshotUseCase = defineAuthorizedWorkspaceUseCase(
175207 }
176208 }
177209
178- const [ snapshot ] = await db
179- . select ( )
180- . from ( workflowExecutionSnapshots )
181- . where ( eq ( workflowExecutionSnapshots . id , record . stateSnapshotId ) )
182- . limit ( 1 )
183- if ( ! snapshot ) {
210+ const workflowState = ( await readSnapshotStates ( [ record . stateSnapshotId ] , input . signal ) ) . get (
211+ record . stateSnapshotId
212+ )
213+ if ( workflowState === undefined ) {
184214 throw new OrchestrationError ( 'not_found' , 'Workflow state snapshot not found' )
185215 }
186216
217+ input . signal ?. throwIfAborted ( )
187218 const executionData = ( await materializeExecutionData (
188- record . executionData as Record < string , unknown > | null ,
219+ ( await readExecutionData ( record . executionId ) ) as Record < string , unknown > | null ,
189220 {
190221 workspaceId : context . workspaceId ,
191222 workflowId : record . workflowId ,
@@ -201,34 +232,17 @@ const authorizedReadExecutionSnapshotUseCase = defineAuthorizedWorkspaceUseCase(
201232 } )
202233 }
203234
204- const childSnapshotIds = collectChildSnapshotIds ( traceSpans )
205- const childWorkflowSnapshots : Array < { id : string ; stateData : unknown } > = [ ]
206- for ( let index = 0 ; index < childSnapshotIds . length ; index += CHILD_SNAPSHOT_QUERY_CHUNK_SIZE ) {
207- input . signal ?. throwIfAborted ( )
208- childWorkflowSnapshots . push (
209- ...( await db
210- . select ( {
211- id : workflowExecutionSnapshots . id ,
212- stateData : workflowExecutionSnapshots . stateData ,
213- } )
214- . from ( workflowExecutionSnapshots )
215- . where (
216- inArray (
217- workflowExecutionSnapshots . id ,
218- childSnapshotIds . slice ( index , index + CHILD_SNAPSHOT_QUERY_CHUNK_SIZE )
219- )
220- ) )
221- )
222- }
235+ const childWorkflowSnapshots = await readSnapshotStates (
236+ collectChildSnapshotIds ( traceSpans ) ,
237+ input . signal
238+ )
223239
224240 input . signal ?. throwIfAborted ( )
225241 return {
226242 executionId : record . executionId ,
227243 workflowId : record . workflowId ,
228- workflowState : snapshot . stateData as Record < string , unknown > ,
229- childWorkflowSnapshots : Object . fromEntries (
230- childWorkflowSnapshots . map ( ( child ) => [ child . id , child . stateData ] )
231- ) ,
244+ workflowState : workflowState as Record < string , unknown > ,
245+ childWorkflowSnapshots : Object . fromEntries ( childWorkflowSnapshots ) ,
232246 executionMetadata : {
233247 trigger : record . trigger ,
234248 startedAt : record . startedAt . toISOString ( ) ,
0 commit comments