( executionData: Record<string, unknown> | null | undefined, context: TraceStoreReadContext )
| 131 | * missing/unreadable (e.g. post-retention) so reads degrade rather than crash. |
| 132 | */ |
| 133 | export async function materializeExecutionData( |
| 134 | executionData: Record<string, unknown> | null | undefined, |
| 135 | context: TraceStoreReadContext |
| 136 | ): Promise<Record<string, unknown>> { |
| 137 | if (!executionData) return {} |
| 138 | |
| 139 | const ref = executionData[TRACE_STORE_REF_KEY] |
| 140 | if (!isLargeValueRef(ref)) return executionData |
| 141 | |
| 142 | const { [TRACE_STORE_REF_KEY]: _pointer, ...markers } = executionData |
| 143 | |
| 144 | if (!context.workspaceId) return markers |
| 145 | |
| 146 | // workflowId is `set null` on workflow delete, but the ref key embeds the |
| 147 | // original workflowId — recover it so deleted-workflow logs stay readable. |
| 148 | // Workspace authorization still comes from the (authorized) caller context. |
| 149 | const workflowId = context.workflowId ?? workflowIdFromStorageKey(ref.key) |
| 150 | if (!workflowId) return markers |
| 151 | |
| 152 | try { |
| 153 | const materialized = await materializeLargeValueRef(ref, { |
| 154 | workspaceId: context.workspaceId, |
| 155 | workflowId, |
| 156 | executionId: context.executionId, |
| 157 | maxBytes: ref.size, |
| 158 | // Read-only: the value is already referenced by its own execution; don't |
| 159 | // re-register (or fail) on every view/export. |
| 160 | trackReference: false, |
| 161 | }) |
| 162 | |
| 163 | if (!materialized || typeof materialized !== 'object') { |
| 164 | logger.warn('Trace store object unavailable; returning metadata only', { |
| 165 | executionId: context.executionId, |
| 166 | key: ref.key, |
| 167 | }) |
| 168 | return markers |
| 169 | } |
| 170 | |
| 171 | return { ...(materialized as Record<string, unknown>), ...markers } |
| 172 | } catch (error) { |
| 173 | logger.warn('Failed to materialize execution data; returning metadata only', { |
| 174 | executionId: context.executionId, |
| 175 | error: toError(error).message, |
| 176 | }) |
| 177 | return markers |
| 178 | } |
| 179 | } |
no test coverage detected