Seed relay fetches plain overviews by default
For 2026 a.b.ath articles Eweka's gzip replies have a long tail (p90 12.4 s per 20k vs 3.9 s plain; 6.1k vs 10.5k headers/s). SEED_NNTP_COMPRESS turns compression back on; plain replies are deflated for nodes asynchronously. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
7893876435
commit
3e6b5bed56
5 files changed
+21
-5
No files matched your search
@@ -31,7 +31,8 @@ class SeedFetchPool {
|
||||
}
|
||||
|
||||
/**
|
||||
* A failure is retried once without compression, on a connection of its
|
||||
* Pooled connections fetch compressed only with SEED_NNTP_COMPRESS (plain is
|
||||
* faster for recent 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
|
||||
@@ -105,7 +106,7 @@ class SeedFetchPool {
|
||||
if (this.open < this.size) {
|
||||
this.open++
|
||||
try {
|
||||
return { client: await this.connect(true), usedAt: Date.now() }
|
||||
return { client: await this.connect(indexerConfig.seed.nntpCompress), usedAt: Date.now() }
|
||||
} catch (error) {
|
||||
this.open--
|
||||
this.waiters.shift()?.()
|
||||
|
||||
@@ -72,6 +72,12 @@ export default {
|
||||
* answered" in 10 minutes came in 0.3 s on a fresh connection.
|
||||
*/
|
||||
nntpTimeoutMs: env.get('SEED_NNTP_TIMEOUT_MS', 90 * 1000),
|
||||
/**
|
||||
* Ask the news server for gzip-compressed overviews. Off: for 2026 articles Eweka's
|
||||
* compressed replies have a long tail (p90 12.4 s per 20k, against 3.9 s plain; 6.1k
|
||||
* against 10.5k headers/s, LOG.md 2026-10-06 (9)). Nodes get gzip from the relay either way.
|
||||
*/
|
||||
nntpCompress: env.get('SEED_NNTP_COMPRESS', false),
|
||||
},
|
||||
|
||||
backfill: {
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { promisify } from 'node:util'
|
||||
import net from 'node:net'
|
||||
import tls from 'node:tls'
|
||||
import { deflateSync, unzipSync } from 'node:zlib'
|
||||
import { deflate, deflateSync, unzipSync } from 'node:zlib'
|
||||
|
||||
const deflateAsync = promisify(deflate)
|
||||
|
||||
export interface XoverClientOptions {
|
||||
host: string
|
||||
@@ -100,7 +103,9 @@ export class XoverClient {
|
||||
const reply = await this.command(`XOVER ${from}-${to}`)
|
||||
if (reply.startsWith('420') || reply.startsWith('423')) return deflateSync(Buffer.alloc(0))
|
||||
await this.expect(reply, ['224'])
|
||||
return reply.includes('COMPRESS=GZIP') ? (await this.compressedRaw()).raw : deflateSync(Buffer.from(await this.plainBody()))
|
||||
if (reply.includes('COMPRESS=GZIP')) return (await this.compressedRaw()).raw
|
||||
// Plain replies (the relay's default): compressed off the event loop, at the fastest level.
|
||||
return deflateAsync(Buffer.from(await this.plainBody()), { level: 1 })
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -83,6 +83,7 @@ export default await Env.create(new URL('../', import.meta.url), {
|
||||
NNTP_TLS_SERVERNAME: Env.schema.string.optional(),
|
||||
SEED_NNTP_CONNECTIONS: Env.schema.number.optional(),
|
||||
SEED_NNTP_TIMEOUT_MS: Env.schema.number.optional(),
|
||||
SEED_NNTP_COMPRESS: Env.schema.boolean.optional(),
|
||||
|
||||
// Indexer (config/indexer.ts)
|
||||
BACKFILL_MAX_QUEUED: Env.schema.number.optional(),
|
||||
|
||||
@@ -26,7 +26,9 @@ test.group('SeedFetchPool', () => {
|
||||
})
|
||||
})
|
||||
await new Promise<void>((resolve) => server.listen(0, '127.0.0.1', resolve))
|
||||
const saved = { host: nntpConfig.host, port: nntpConfig.port, secure: nntpConfig.secure, connections: indexerConfig.seed.nntpConnections }
|
||||
const saved = { host: nntpConfig.host, port: nntpConfig.port, secure: nntpConfig.secure, connections: indexerConfig.seed.nntpConnections, compress: indexerConfig.seed.nntpCompress }
|
||||
// The fallback from a compressed pooled connection (SEED_NNTP_COMPRESS on).
|
||||
indexerConfig.seed.nntpCompress = true
|
||||
Object.assign(nntpConfig, { host: '127.0.0.1', port: (server.address() as net.AddressInfo).port, secure: false })
|
||||
indexerConfig.seed.nntpConnections = 2
|
||||
try {
|
||||
@@ -39,6 +41,7 @@ test.group('SeedFetchPool', () => {
|
||||
SeedFetchPool.closeIdle()
|
||||
Object.assign(nntpConfig, { host: saved.host, port: saved.port, secure: saved.secure })
|
||||
indexerConfig.seed.nntpConnections = saved.connections
|
||||
indexerConfig.seed.nntpCompress = saved.compress
|
||||
server.close()
|
||||
}
|
||||
})
|
||||
|
||||
Reference in new issue
Block a user