Seed relay: dead NNTP connections found in 90 s and retried
Five ranges "never answered" in 10 minutes, yet their chunk came back in 0.3 s on a fresh connection: the news server drops idle connections without telling, and the pool's next request on one waited for the 10-minute inactivity timeout. Now: SEED_NNTP_TIMEOUT_MS 90 s (inactivity; slow ranges keep streaming), one retry on a fresh connection, and pooled connections idle over 60 s are replaced before use. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
8d86f7d489
commit
028dd90a6f
4 files changed
+72
-5
No files matched your search
@@ -8,8 +8,12 @@ interface Slot {
|
||||
usedAt: number
|
||||
}
|
||||
|
||||
/** A pooled connection unused this long is replaced: the news server may have dropped it. */
|
||||
const IDLE_MS = 2 * 60 * 1000
|
||||
/**
|
||||
* A pooled connection unused this long is replaced: the news server drops
|
||||
* idle connections without telling, and a request on one then hangs until
|
||||
* the inactivity timeout (LOG.md 2026-10-05 (11)).
|
||||
*/
|
||||
const IDLE_MS = 60 * 1000
|
||||
|
||||
/**
|
||||
* NNTP connections in the seed API for relay nodes (CONCEPT.md D38): the
|
||||
@@ -26,7 +30,16 @@ class SeedFetchPool {
|
||||
return indexerConfig.seed.nntpConnections
|
||||
}
|
||||
|
||||
/** Retried once on a fresh connection: a failure is nearly always a dead connection, not the articles. */
|
||||
async fetch(group: string, from: number, to: number): Promise<Buffer> {
|
||||
try {
|
||||
return await this.fetchOnce(group, from, to)
|
||||
} catch {
|
||||
return this.fetchOnce(group, from, to)
|
||||
}
|
||||
}
|
||||
|
||||
private async fetchOnce(group: string, from: number, to: number): Promise<Buffer> {
|
||||
const slot = await this.acquire()
|
||||
let ok = false
|
||||
try {
|
||||
@@ -42,6 +55,14 @@ class SeedFetchPool {
|
||||
}
|
||||
}
|
||||
|
||||
/** Closes the idle connections (tests, shutdown); busy ones close when released. */
|
||||
closeIdle() {
|
||||
for (const slot of this.idle.splice(0)) {
|
||||
slot.client.close()
|
||||
this.open--
|
||||
}
|
||||
}
|
||||
|
||||
private async acquire(): Promise<Slot> {
|
||||
while (true) {
|
||||
const slot = this.idle.pop()
|
||||
|
||||
Reference in new issue
Block a user