fix: artwork cache never throws on body/disk failures
This commit is contained in:
@@ -22,20 +22,24 @@ export async function cacheArtwork(
|
|||||||
): Promise<string | null> {
|
): Promise<string | null> {
|
||||||
if (!url) return null
|
if (!url) return null
|
||||||
const key = createHash('sha256').update(url).digest('hex')
|
const key = createHash('sha256').update(url).digest('hex')
|
||||||
mkdirSync(artworkDir, { recursive: true })
|
|
||||||
for (const ext of Object.values(EXT_BY_TYPE)) {
|
|
||||||
if (existsSync(path.join(artworkDir, key + ext))) return key + ext
|
|
||||||
}
|
|
||||||
let res: Response
|
|
||||||
try {
|
try {
|
||||||
res = await fetchImpl(url)
|
mkdirSync(artworkDir, { recursive: true })
|
||||||
|
for (const ext of Object.values(EXT_BY_TYPE)) {
|
||||||
|
if (existsSync(path.join(artworkDir, key + ext))) return key + ext
|
||||||
|
}
|
||||||
|
let res: Response
|
||||||
|
try {
|
||||||
|
res = await fetchImpl(url)
|
||||||
|
} catch {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
if (!res.ok) return null
|
||||||
|
const type = (res.headers.get('content-type') ?? '').split(';')[0]?.trim() ?? ''
|
||||||
|
const ext = EXT_BY_TYPE[type] ?? '.jpg'
|
||||||
|
const buf = Buffer.from(await res.arrayBuffer())
|
||||||
|
await writeFile(path.join(artworkDir, key + ext), buf)
|
||||||
|
return key + ext
|
||||||
} catch {
|
} catch {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
if (!res.ok) return null
|
|
||||||
const type = (res.headers.get('content-type') ?? '').split(';')[0]?.trim() ?? ''
|
|
||||||
const ext = EXT_BY_TYPE[type] ?? '.jpg'
|
|
||||||
const buf = Buffer.from(await res.arrayBuffer())
|
|
||||||
await writeFile(path.join(artworkDir, key + ext), buf)
|
|
||||||
return key + ext
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,4 +75,20 @@ describe('cacheArtwork', () => {
|
|||||||
rmSync(dir, { recursive: true, force: true })
|
rmSync(dir, { recursive: true, force: true })
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('returns null when the response body fails mid-download', async () => {
|
||||||
|
const dir = tempDir()
|
||||||
|
try {
|
||||||
|
const fetcher = (async () =>
|
||||||
|
new Response(new ReadableStream({
|
||||||
|
start(controller) {
|
||||||
|
controller.enqueue(new Uint8Array([0xff]))
|
||||||
|
controller.error(new TypeError('network error mid-body'))
|
||||||
|
},
|
||||||
|
}), { status: 200, headers: { 'content-type': 'image/jpeg' } })) as unknown as typeof fetch
|
||||||
|
expect(await cacheArtwork(dir, 'https://x/abort.jpg', fetcher)).toBeNull()
|
||||||
|
} finally {
|
||||||
|
rmSync(dir, { recursive: true, force: true })
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user