A missing first article is an inspection result, not a failure
Eweka answers 'no such article' after ~450 ms; a quarter of inspection requests were for missing articles and each failed job was retried up to three times. Files get content_type 'missing' instead; homelab also records it from failure reports of nodes not rebuilt yet. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
bef68075be
commit
61192690a7
6 files changed
+57
-5
No files matched your search
+16
-1
@@ -83,6 +83,11 @@ export function chunkMd5(data: Buffer, fileSize: number): string | undefined {
|
||||
return createHash('md5').update(data.subarray(0, FIRST_CHUNK)).digest('hex')
|
||||
}
|
||||
|
||||
/** A "no such article" answer: 430 from the news server, 410 from the seed relay. */
|
||||
export function isMissingArticle(error: unknown): boolean {
|
||||
return /(^|[^0-9])(430|410)([^0-9]|$)/.test(String((error as any)?.message ?? error)) && !/timed out|no answer/i.test(String((error as any)?.message))
|
||||
}
|
||||
|
||||
/** Decodes a body; some tools declare a size that leaves out a header (nzbe), the CRC still has to match. */
|
||||
export function decodeBody(body: Buffer): DecodedSegment {
|
||||
try {
|
||||
@@ -132,7 +137,17 @@ export async function probeInspection(
|
||||
fetch: BodyFetcher,
|
||||
warn: (message: string) => void = () => {}
|
||||
): Promise<InspectProbe> {
|
||||
const segment = decodeBody(await fetch(task.segments[0].id))
|
||||
let body: Buffer
|
||||
try {
|
||||
body = await fetch(task.segments[0].id)
|
||||
} catch (error: any) {
|
||||
// The server no longer has it (430; 410 through the seed relay), typically a takedown. A final
|
||||
// answer, and an expensive one: Eweka takes ~450 ms per missing article, so it isn't retried
|
||||
// (LOG.md 2026-10-06 (14)).
|
||||
if (isMissingArticle(error)) return { size: 0, contentType: 'missing', md5_16k: null, yencName: '' }
|
||||
throw error
|
||||
}
|
||||
const segment = decodeBody(body)
|
||||
const size = segment.meta.begin.size
|
||||
const contentType = sniffContentType(segment.data)
|
||||
const probe: InspectProbe = {
|
||||
|
||||
Reference in new issue
Block a user