fix(client): file download cancellation issues
This commit is contained in:
parent
3eaceedb8b
commit
391049b86f
1 changed files with 28 additions and 1 deletions
|
@ -32,6 +32,9 @@ export async function* downloadAsIterable(
|
|||
let dcId = params?.dcId
|
||||
let fileSize = params?.fileSize
|
||||
|
||||
const abortSignal = params?.abortSignal
|
||||
let aborted = false
|
||||
|
||||
let location: tl.TypeInputFileLocation | tl.TypeInputWebFileLocation
|
||||
if (input instanceof FileLocation) {
|
||||
let locationInner = input.location
|
||||
|
@ -102,6 +105,10 @@ export async function* downloadAsIterable(
|
|||
const downloadChunk = async (chunk = nextWorkerChunkIdx++): Promise<void> => {
|
||||
let result: tl.RpcCallReturn['upload.getFile'] | tl.RpcCallReturn['upload.getWebFile']
|
||||
|
||||
if (aborted) {
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
result = await client.call(
|
||||
{
|
||||
|
@ -111,9 +118,15 @@ export async function* downloadAsIterable(
|
|||
offset: chunkSize * chunk,
|
||||
limit: chunkSize,
|
||||
},
|
||||
{ dcId, kind: connectionKind, abortSignal: params?.abortSignal },
|
||||
{
|
||||
dcId,
|
||||
kind: connectionKind,
|
||||
maxRetryCount: Infinity, // retry until explicitly aborted (or finished)
|
||||
abortSignal,
|
||||
},
|
||||
)
|
||||
} catch (e: unknown) {
|
||||
if (e instanceof DOMException && e.name === 'AbortError') return
|
||||
if (!tl.RpcError.is(e)) throw e
|
||||
|
||||
if (e.is('FILE_MIGRATE_%d')) {
|
||||
|
@ -134,6 +147,10 @@ export async function* downloadAsIterable(
|
|||
throw new MtUnsupportedError('Received CDN redirect, which is not supported (yet)')
|
||||
}
|
||||
|
||||
if (aborted) {
|
||||
return
|
||||
}
|
||||
|
||||
if (result._ === 'upload.webFile' && result.size && limitBytes === Infinity) {
|
||||
limitBytes = result.size
|
||||
numChunks = ~~((limitBytes + chunkSize - offset - 1) / chunkSize)
|
||||
|
@ -155,12 +172,22 @@ export async function* downloadAsIterable(
|
|||
.catch((e) => {
|
||||
client.log.debug('download workers errored: %s', e.message)
|
||||
error = e
|
||||
aborted = true // not really aborted, but we dont want to download more chunks
|
||||
nextChunkCv.notify()
|
||||
})
|
||||
.then(() => {
|
||||
client.log.debug('download workers finished')
|
||||
})
|
||||
|
||||
// to avoid MaxListenersExceededWarning we do this instead
|
||||
// already sent requests can go to hell (they will get ignored)
|
||||
abortSignal?.addEventListener('abort', () => {
|
||||
client.log.debug('download aborted')
|
||||
error = abortSignal.reason
|
||||
aborted = true
|
||||
nextChunkCv.notify()
|
||||
})
|
||||
|
||||
let position = offset
|
||||
|
||||
while (position < limitBytes) {
|
||||
|
|
Loading…
Reference in a new issue