Skip to content

Commit 944f24d

Browse files
committed
fix(logs): read a snapshot view's execution data with the timing and cost it pairs with
1 parent 857c129 commit 944f24d

2 files changed

Lines changed: 43 additions & 11 deletions

File tree

‎apps/sim/lib/logs/application/read-execution-snapshot.test.ts‎

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,13 @@ const workspaceContext = {
6666
billedAccountUserId: 'billing-owner-1',
6767
}
6868

69+
const completedRun = {
70+
executionData: null,
71+
endedAt: new Date('2026-08-05T12:00:01.000Z'),
72+
totalDurationMs: 1000,
73+
costTotal: '0.75',
74+
}
75+
6976
const workflowRecord = {
7077
id: 'log-1',
7178
workflowId: 'workflow-1',
@@ -140,7 +147,7 @@ describe('readExecutionSnapshot spend projection', () => {
140147
queueSelects(
141148
[workflowRecord],
142149
[{ id: 'snapshot-1', stateData: { blocks: {} } }],
143-
[{ executionData: null }]
150+
[completedRun]
144151
)
145152

146153
const result = await read(principal, 'run-1')
@@ -162,12 +169,28 @@ describe('readExecutionSnapshot spend projection', () => {
162169
queueSelects(
163170
[workflowRecord],
164171
[{ id: 'snapshot-1', stateData: { blocks: {} } }],
165-
[{ executionData: null }]
172+
[completedRun]
166173
)
167174

168175
const result = await read(executorPrincipal, 'run-1')
169176

170177
expect(result.executionMetadata.cost).toEqual({ total: 0.75 })
171178
expect(permissionGroupScopeMockFns.mockResolvePermissionGroupConfig).not.toHaveBeenCalled()
172179
})
180+
181+
it('reports the timing and cost read with the execution data, not the earlier context', async () => {
182+
queueSelects(
183+
[{ ...workflowRecord, endedAt: null, totalDurationMs: null, costTotal: null }],
184+
[{ id: 'snapshot-1', stateData: { blocks: {} } }],
185+
[completedRun]
186+
)
187+
188+
const result = await read(executorPrincipal, 'run-1')
189+
190+
expect(result.executionMetadata).toMatchObject({
191+
endedAt: '2026-08-05T12:00:01.000Z',
192+
totalDurationMs: 1000,
193+
cost: { total: 0.75 },
194+
})
195+
})
173196
})

‎apps/sim/lib/logs/application/read-execution-snapshot.ts‎

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -138,16 +138,23 @@ async function readSnapshotStates(
138138
}
139139

140140
/**
141-
* Read here, after authorization, rather than with the context: a caller the
142-
* use case refuses never fetches the run's execution data.
141+
* The run's execution data with the fields a completion write changes alongside it,
142+
* read in one statement after authorization: a caller the use case refuses never
143+
* fetches the payload, and a run finishing mid-request cannot pair new data with
144+
* stale timing or cost.
143145
*/
144-
async function readExecutionData(executionId: string): Promise<unknown> {
146+
async function readRunCompletion(executionId: string) {
145147
const [row] = await db
146-
.select({ executionData: workflowExecutionLogs.executionData })
148+
.select({
149+
executionData: workflowExecutionLogs.executionData,
150+
endedAt: workflowExecutionLogs.endedAt,
151+
totalDurationMs: workflowExecutionLogs.totalDurationMs,
152+
costTotal: workflowExecutionLogs.costTotal,
153+
})
147154
.from(workflowExecutionLogs)
148155
.where(eq(workflowExecutionLogs.executionId, executionId))
149156
.limit(1)
150-
return row?.executionData ?? null
157+
return row
151158
}
152159

153160
function collectChildSnapshotIds(traceSpans: TraceSpan[]): string[] {
@@ -215,8 +222,10 @@ const authorizedReadExecutionSnapshotUseCase = defineAuthorizedWorkspaceUseCase(
215222
}
216223

217224
input.signal?.throwIfAborted()
225+
const completion = await readRunCompletion(record.executionId)
226+
if (!completion) throw new OrchestrationError('not_found', 'Workflow execution not found')
218227
const executionData = (await materializeExecutionData(
219-
(await readExecutionData(record.executionId)) as Record<string, unknown> | null,
228+
completion.executionData as Record<string, unknown> | null,
220229
{
221230
workspaceId: context.workspaceId,
222231
workflowId: record.workflowId,
@@ -246,9 +255,9 @@ const authorizedReadExecutionSnapshotUseCase = defineAuthorizedWorkspaceUseCase(
246255
executionMetadata: {
247256
trigger: record.trigger,
248257
startedAt: record.startedAt.toISOString(),
249-
endedAt: record.endedAt?.toISOString(),
250-
totalDurationMs: record.totalDurationMs,
251-
cost: projectCostTotal(record.costTotal, projection),
258+
endedAt: completion.endedAt?.toISOString(),
259+
totalDurationMs: completion.totalDurationMs,
260+
cost: projectCostTotal(completion.costTotal, projection),
252261
},
253262
}
254263
},

0 commit comments

Comments
 (0)