(
workspaceId: WorkspaceId,
streamInfo: WorkspaceStreamInfo
)
| 1269 | // Checks if a soft interrupt is necessary, and performs one if so |
| 1270 | // Similar to cancelStreamSafely but performs cleanup without blocking |
| 1271 | private async checkSoftCancelStream( |
| 1272 | workspaceId: WorkspaceId, |
| 1273 | streamInfo: WorkspaceStreamInfo |
| 1274 | ): Promise<void> { |
| 1275 | if (!streamInfo.softInterrupt.pending) return; |
| 1276 | try { |
| 1277 | streamInfo.state = StreamState.STOPPING; |
| 1278 | |
| 1279 | // Flush any pending partial write immediately (preserves work on interruption) |
| 1280 | await this.flushPartialWrite(workspaceId, streamInfo); |
| 1281 | |
| 1282 | streamInfo.abortController.abort(); |
| 1283 | |
| 1284 | // Return back to the stream loop so we can wait for it to finish before |
| 1285 | // sending the stream abort event. |
| 1286 | const { abandonPartial, abortReason } = streamInfo.softInterrupt; |
| 1287 | void this.cleanupAbortedStream(workspaceId, streamInfo, abortReason, abandonPartial); |
| 1288 | } catch (error) { |
| 1289 | log.error("Error during stream cancellation:", error); |
| 1290 | // Force cleanup even if cancellation fails |
| 1291 | this.workspaceStreams.delete(workspaceId); |
| 1292 | } |
| 1293 | } |
| 1294 | |
| 1295 | private async cleanupAbortedStream( |
| 1296 | workspaceId: WorkspaceId, |
no test coverage detected