( value: unknown, json: string, size: number, context: LargeValueStoreContext )
| 160 | } |
| 161 | |
| 162 | export async function storeLargeValue( |
| 163 | value: unknown, |
| 164 | json: string, |
| 165 | size: number, |
| 166 | context: LargeValueStoreContext |
| 167 | ): Promise<LargeValueRef> { |
| 168 | assertDurableLargeValueSize(size) |
| 169 | const referencedKeys = collectLargeValueKeys(value) |
| 170 | const id = `lv_${generateShortId(12)}` |
| 171 | let key = await persistValue(id, json, context) |
| 172 | if (key) { |
| 173 | // Only clean up the uploaded object when registration definitively did NOT |
| 174 | // record ownership (returns false). If registration THROWS, the metadata |
| 175 | // state is uncertain (a row may have partially committed), so we propagate |
| 176 | // without deleting — deleting could orphan a metadata row pointing at a |
| 177 | // now-missing object. |
| 178 | const registered = await registerPersistedValueOwner(key, size, referencedKeys, context) |
| 179 | if (!registered) { |
| 180 | await deleteUntrackedPersistedValue(key) |
| 181 | if (context.requireDurable) { |
| 182 | throw new Error('Failed to persist large execution value metadata') |
| 183 | } |
| 184 | key = undefined |
| 185 | } |
| 186 | } |
| 187 | const cached = cacheLargeValue(id, value, size, context, { recoverable: Boolean(key) }) |
| 188 | if (!key && !cached) { |
| 189 | throw new Error('Cannot retain large execution value without durable storage') |
| 190 | } |
| 191 | |
| 192 | return { |
| 193 | __simLargeValueRef: true, |
| 194 | version: LARGE_VALUE_REF_VERSION, |
| 195 | id, |
| 196 | kind: getKind(value), |
| 197 | size, |
| 198 | key, |
| 199 | executionId: context.executionId, |
| 200 | preview: getPreview(value), |
| 201 | } |
| 202 | } |
| 203 | |
| 204 | export async function materializeLargeValueRef( |
| 205 | ref: LargeValueRef, |
no test coverage detected