import env from '#start/env' import app from '@adonisjs/core/services/app' /** The coordinator (REBUILD.md, part 1). */ export default { /** Articles per range. */ rangeArticles: env.get('RANGE_ARTICLES', 2_000_000), /** * Articles per XOVER chunk (spool files, stream frames). Eweka takes * ~1.5–2 s per command whatever its size: one connection read 9–15k * lines/s in chunks of 25k, ~20k in 50k, ~30k in 100k and 200k (LOG.md * 2026-10-09). */ chunkArticles: env.get('CHUNK_ARTICLES', 100_000), /** * The live tail (REBUILD.md, coordinator): new articles become ranges * every `everySeconds` (one LIST ACTIVE per name prefix), leased and * fetched before any history. A group gets a tail range once it has * `minArticles` new (a chunk) or its oldest unplanned article waited * `maxDelayMinutes`, so a quiet group doesn't make a range every round. */ tail: { everySeconds: env.get('TAIL_EVERY_SECONDS', 120), minArticles: env.get('TAIL_MIN_ARTICLES', 100_000), maxDelayMinutes: env.get('TAIL_MAX_DELAY_MINUTES', 15), /** Before the history's 0 (oldest) … 1000 (newest). */ priority: -1, }, /** A leased range without a heartbeat for this long goes back to the queue. */ leaseTtlSeconds: env.get('LEASE_TTL_SECONDS', 15 * 60), /** NNTP connections the coordinator fetches headers with. */ nntpConnections: env.get('NNTP_CONNECTIONS', 4), /** * A reply with no data for this long fails, and its connection is replaced. * Eweka sometimes stops answering on long-lived connections (all 40 quiet, * a fresh one answers in seconds; LOG.md 2026-10-09 (14)): at 10 minutes * the prefetcher nearly stopped. Data arrives within seconds otherwise. */ nntpTimeoutMs: env.get('NNTP_TIMEOUT_MS', 2 * 60 * 1000), /** * A chunk still coming in after this long is given up (its connection * closed) and fetched again: a reply that trickles never goes quiet long * enough for nntpTimeoutMs, and kept a worker waiting on one chunk for an * hour (LOG.md 2026-10-10 (2)). Chunks take 3–35 s; at 300 s, 258 were * given up in 3 hours (~1.4 a minute, each holding a connection 5 minutes); * at 180 s 60 in 15 minutes, ~30% of 40 connections' time, while finished * chunks took 24 s on average. */ nntpChunkDeadlineMs: env.get('NNTP_CHUNK_DEADLINE_SECONDS', 90) * 1000, /** * A chunk not fetched after this long is asked again on another * connection; the first answer wins and the other connection is closed. * Eweka stalls single requests: the same chunk took 27–52 s on one * connection and 1–9 s on another at the same moment; median ~3 s * (LOG.md 2026-10-09 (15)). Measured in production (40 + 6 connections vs * 40, 15 min each): 280k vs 273k articles/s, within the noise; the second * request won half the time. Off by default. */ nntpHedgeAfterMs: env.get('NNTP_HEDGE_AFTER_SECONDS', 10) * 1000, /** Of nntpConnections, kept for those second requests (the prefetcher's loops are the rest). 0: no hedging. */ nntpHedgeConnections: env.get('NNTP_HEDGE_CONNECTIONS', 0), /** * A connection is closed after this long (when it's free), and a fresh one * opened. 0: never. Requests were as often slow (>10 s) on connections * under 2 minutes old as on ones over 10 (~25–35%; LOG.md 2026-10-09 (16)). */ nntpConnectionMaxMs: env.get('NNTP_CONNECTION_MAX_MINUTES', 0) * 60 * 1000, spool: { dir: env.get('SPOOL_DIR', app.tmpPath('spool')), /** Ranges kept fetched ahead, per active lease. */ aheadPerLease: env.get('SPOOL_AHEAD_PER_LEASE', 4), /** At least this many ranges ahead, so the first leases start at once. */ minAhead: env.get('SPOOL_MIN_AHEAD', 2), maxBytes: env.get('SPOOL_MAX_GB', 10) * 1e9, /** * At most this many connections on one range, and on one group, at a * time (0: no limit): spreads the requests over ranges and groups instead * of all on the next chunks of the first ranges. Homelab, 40 connections, * 12 min each, alternated: unlimited (on ~10 ranges) 281k and 167k * articles/s, 2 per range and 4 per group (on ~22) 319k and 296k, with * shorter chunk times (11.5 vs 13–24 s; LOG.md 2026-10-09 (18)). Needs * targets for it: aheadPerLease 4. */ perRange: env.get('PREFETCH_PER_RANGE', 2), perGroup: env.get('PREFETCH_PER_GROUP', 4), }, }