Seed relay: a stalled compressed XOVER is fetched again uncompressed
The four ranges kept failing on fresh connections too: in gzip mode Eweka stops some chunks partway (a.b.ath 49701720000: 19,672 of 20,000 overviews, the last line cut, then silence), while the same chunk without compression comes in 0.3 s. A failed relay chunk is now retried once without compression on a connection of its own (dead pooled connections are covered by the same retry). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
028dd90a6f
commit
b7ae8267c6
2 files changed
+38
-15
No files matched your search
@@ -30,15 +30,45 @@ class SeedFetchPool {
|
||||
return indexerConfig.seed.nntpConnections
|
||||
}
|
||||
|
||||
/** Retried once on a fresh connection: a failure is nearly always a dead connection, not the articles. */
|
||||
/**
|
||||
* A failure is retried once without compression, on a connection of its
|
||||
* own: either the pooled connection was dead (dropped while idle), or the
|
||||
* server stalled mid-reply in compressed mode. Eweka does that for some
|
||||
* chunks: it stops after most of the stream and never sends the rest
|
||||
* (a.b.ath 49701720000: 19,672 of 20,000 overviews, then silence), while
|
||||
* the same chunk uncompressed comes in 0.3 s (LOG.md 2026-10-05 (11)).
|
||||
*/
|
||||
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)
|
||||
return this.fetchPlain(group, from, to)
|
||||
}
|
||||
}
|
||||
|
||||
private async fetchPlain(group: string, from: number, to: number): Promise<Buffer> {
|
||||
const client = await this.connect(false)
|
||||
try {
|
||||
await client.group(group)
|
||||
return await client.xoverRaw(from, to)
|
||||
} finally {
|
||||
client.close()
|
||||
}
|
||||
}
|
||||
|
||||
private connect(compress: boolean) {
|
||||
return XoverClient.connect({
|
||||
host: nntpConfig.host,
|
||||
port: nntpConfig.port,
|
||||
secure: nntpConfig.secure,
|
||||
servername: nntpConfig.tlsServername,
|
||||
user: nntpConfig.user,
|
||||
password: nntpConfig.password?.release(),
|
||||
timeoutMs: indexerConfig.seed.nntpTimeoutMs,
|
||||
compress,
|
||||
})
|
||||
}
|
||||
|
||||
private async fetchOnce(group: string, from: number, to: number): Promise<Buffer> {
|
||||
const slot = await this.acquire()
|
||||
let ok = false
|
||||
@@ -75,17 +105,7 @@ class SeedFetchPool {
|
||||
if (this.open < this.size) {
|
||||
this.open++
|
||||
try {
|
||||
const client = await XoverClient.connect({
|
||||
host: nntpConfig.host,
|
||||
port: nntpConfig.port,
|
||||
secure: nntpConfig.secure,
|
||||
servername: nntpConfig.tlsServername,
|
||||
user: nntpConfig.user,
|
||||
password: nntpConfig.password?.release(),
|
||||
timeoutMs: indexerConfig.seed.nntpTimeoutMs,
|
||||
compress: true,
|
||||
})
|
||||
return { client, usedAt: Date.now() }
|
||||
return { client: await this.connect(true), usedAt: Date.now() }
|
||||
} catch (error) {
|
||||
this.open--
|
||||
this.waiters.shift()?.()
|
||||
|
||||
Reference in new issue
Block a user