Files
vercel__next.js/test/e2e/cancel-request/streamable.ts
Hendrik Liebau ddfc90df92 Unflake "cancels stream making progress" test (#71422)
x-ref: [Flakiness
Metrics](https://app.datadoghq.com/ci/test-runs?query=test_level%3Atest%20env%3Aci%20%40git.repository.id%3Agithub.com%2Fvercel%2Fnext.js%20%40test.service%3Anextjs%20%40test.status%3Afail%20%40test.name%3A%22streaming%20responses%20cancel%20inner%20stream%20after%20disconnect%20edge%20pages%20api%20cancels%20stream%20making%20progress%22&agg_m=count&agg_m_source=base&agg_t=count&currentTab=overview&eventStack=&fromUser=false&index=citest&start=1728463943572&end=1729068743572&paused=false)

In #71163, we added to the `Streamable` handling the case where the
request might already be aborted before the response was sent or had a
chance to be consumed.

For the "cancels stream making progress" however, the request may not be
aborted, and instead only the response is destroyed, leading to the
`cancel` method of the `Streamable` being called, but not the `abort`
method.

To handle all cases, we're now resolving the `finished` promise of the
`Streamable` when either `abort` or `cancel` are called.
2024-10-17 16:32:57 +02:00

31 lines
645 B
TypeScript

import { Deferred, sleep } from './sleep'
export function Streamable(write: number) {
const encoder = new TextEncoder()
const canceled = new Deferred()
const aborted = new Deferred()
let i = 0
const streamable = {
finished: Promise.any([canceled.promise, aborted.promise]).then(() => i),
abort() {
aborted.resolve()
},
stream: new ReadableStream({
async pull(controller) {
if (i >= write) {
return
}
await sleep(100)
controller.enqueue(encoder.encode(String(i++)))
},
cancel() {
canceled.resolve()
},
}),
}
return streamable
}