Files
usenet-indexer/tests/unit/seed_fetch_pool.spec.ts
T
Daan MeijerandClaude Opus 5.5 3e6b5bed56
Test and deploy / test (push) Successful in 1m6s
Test and deploy / deploy (push) Successful in 1m43s
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>
2026-10-06 15:49:21 +02:00

49 lines
2.5 KiB
TypeScript

import { test } from '@japa/runner'
import net from 'node:net'
import { unzipSync } from 'node:zlib'
import nntpConfig from '#config/nntp'
import indexerConfig from '#config/indexer'
import SeedFetchPool from '#services/SeedFetchPool'
import { parseOverviews } from '#lib/nntp/xover_client'
test.group('SeedFetchPool', () => {
test('a chunk that fails (dead connection, stalled compressed reply) is fetched again uncompressed', async ({ assert }) => {
let connections = 0
const compressAsked: Record<number, boolean> = {}
const server = net.createServer((sock) => {
const n = ++connections
sock.write('200 welcome\r\n')
sock.on('data', (chunk) => {
for (const line of chunk.toString().split('\r\n').filter(Boolean)) {
if (line.startsWith('AUTHINFO USER')) sock.write('381 more\r\n')
else if (line.startsWith('AUTHINFO PASS')) sock.write('281 ok\r\n')
else if (line.startsWith('XFEATURE')) (compressAsked[n] = true), sock.write('500 no\r\n')
else if (line.startsWith('GROUP')) sock.write('211 1 7 7 a.b.test\r\n')
// The first connection dies as the request arrives, like one the server dropped while idle.
else if (line.startsWith('XOVER') && n === 1) sock.destroy()
else if (line.startsWith('XOVER')) sock.write('224 overviews\r\n7\tsubject\tposter\tdate\t<a@b>\t\t10\t1\r\n.\r\n')
}
})
})
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, 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 {
const raw = await SeedFetchPool.fetch('a.b.test', 7, 7)
assert.deepEqual(parseOverviews(unzipSync(raw).toString('utf8')).map(([n]) => n), [7])
assert.equal(connections, 2)
// The pooled connection asked for gzip; the retry didn't.
assert.deepEqual(compressAsked, { 1: true })
} finally {
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()
}
})
})