fix(core): improved file downloading

This commit is contained in:
alina 🌸 2024-12-26 19:59:42 +03:00
parent 3068c07347
commit da10537b9a
Signed by: teidesu
SSH key fingerprint: SHA256:uNeCpw6aTSU4aIObXLvHfLkDa82HWH9EiOj9AXOIRpI

View file

@ -38,7 +38,7 @@ export async function* downloadAsIterable(
let fileSize = params?.fileSize let fileSize = params?.fileSize
const abortSignal = params?.abortSignal const abortSignal = params?.abortSignal
let aborted = false let ended = false
let location: tl.TypeInputFileLocation | tl.TypeInputWebFileLocation let location: tl.TypeInputFileLocation | tl.TypeInputWebFileLocation
if (input instanceof FileLocation) { if (input instanceof FileLocation) {
@ -92,7 +92,9 @@ export async function* downloadAsIterable(
const nextChunkCv = new ConditionVariable() const nextChunkCv = new ConditionVariable()
const buffer: Record<number, Uint8Array> = {} const buffer: Record<number, Uint8Array> = {}
const isSmall = fileSize && fileSize <= SMALL_FILE_MAX_SIZE // inputPeerPhotoFileLocation files are usually within a few hundred kb-s, so we can treat them as small to avoid extra network load
// (we don't know their exact size, so we can't use the file size limit)
const isSmall = (fileSize && fileSize <= SMALL_FILE_MAX_SIZE) || location._ === 'inputPeerPhotoFileLocation'
let connectionKind: ConnectionKind let connectionKind: ConnectionKind
if (isSmall) { if (isSmall) {
@ -113,7 +115,7 @@ export async function* downloadAsIterable(
const downloadChunk = async (chunk = nextWorkerChunkIdx++): Promise<void> => { const downloadChunk = async (chunk = nextWorkerChunkIdx++): Promise<void> => {
let result: tl.RpcCallReturn['upload.getFile'] | tl.RpcCallReturn['upload.getWebFile'] let result: tl.RpcCallReturn['upload.getFile'] | tl.RpcCallReturn['upload.getWebFile']
if (aborted) { if (ended) {
return return
} }
@ -163,7 +165,7 @@ export async function* downloadAsIterable(
throw new MtUnsupportedError('Received CDN redirect, which is not supported (yet)') throw new MtUnsupportedError('Received CDN redirect, which is not supported (yet)')
} }
if (aborted) { if (ended) {
return return
} }
@ -184,11 +186,13 @@ export async function* downloadAsIterable(
} }
let error: unknown let error: unknown
void Promise.all(Array.from({ length: Math.min(poolSize * REQUESTS_PER_CONNECTION, numChunks) }, downloadChunk)) void Promise.all(Array.from({
length: Math.min(poolSize * (isSmall ? 1 : REQUESTS_PER_CONNECTION), numChunks),
}, downloadChunk))
.catch((e) => { .catch((e) => {
client.log.debug('download workers errored: %e', e) client.log.debug('download workers errored: %e', e)
error = e error = e
aborted = true // not really aborted, but we dont want to download more chunks ended = true // not really aborted, but we dont want to download more chunks
nextChunkCv.notify() nextChunkCv.notify()
}) })
.then(() => { .then(() => {
@ -200,7 +204,7 @@ export async function* downloadAsIterable(
abortSignal?.addEventListener('abort', () => { abortSignal?.addEventListener('abort', () => {
client.log.debug('download aborted') client.log.debug('download aborted')
error = abortSignal.reason error = abortSignal.reason
aborted = true ended = true
nextChunkCv.notify() nextChunkCv.notify()
}) })