Files
usenet-indexer/deploy/compose.yaml
T
Daan MeijerandClaude Opus 5.5 3d0dc6ca1f
Test and deploy / test (push) Successful in 44s
Test and deploy / edge (push) Successful in 1m51s
Test and deploy / deploy (push) Successful in 1m27s
The par2 merge: releases whose files one par2 set describes become one
The prober stores, per probed article that starts a file, the MD5 of its
first 16 KiB (file_hashes), and per par2 body the set's whole file list
(par2_files, par2_sets): FileDesc holds the same hash per file, whatever
the file was renamed to. releases:merge (the merger service, no NNTP)
merges every minute the releases of one group, posted within 48 hours of
a release holding the set's par2, whose files the set describes, into the
one with the most files: chunks, probe candidates, inspections, hashes and
counts move; the par2's shared name when none was readable; release_merges
keeps what went where. Obfuscated uploads whose files were each a release
of their own ("[9/20] - "14f5999a…"", hep: 13,232) become one.

Also: corpus_sweep.py counts the marked ranges without psql's command tag.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 09:37:35 +02:00

158 lines
4.4 KiB
YAML

# Voyager 2 on homelab (deploy/README.md). deploy.sh copies this file to the
# deployment root (/mnt/bulk/usenet-rebuild), next to src/ (the code at the
# deployed commit), .env (credentials, tuning), pg/ and spool/; run
# `docker compose` there. Nothing is shared with voyager 1's compose project.
name: usenet-rebuild
x-app: &app
image: usenet-rebuild:latest
build:
context: ./src
target: app
restart: unless-stopped
env_file: .env
environment: &app-env
NODE_ENV: production
HOST: 0.0.0.0
PORT: 3334
DB_HOST: postgres
DB_PORT: 5432
APP_URL: http://web:3334
SPOOL_DIR: /spool
# Stored XOVER chunks of the ranges marked `capture` (the grouping sweeps' corpus, HDD; app/services/corpus.ts).
CORPUS_DIR: /corpus
volumes:
- ./spool:/spool
- ./corpus:/corpus
stop_grace_period: 60s
depends_on:
migrate:
condition: service_completed_successfully
services:
postgres:
image: postgres:17
restart: unless-stopped
environment:
POSTGRES_USER: ${DB_USER}
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_DB: ${DB_DATABASE}
volumes:
# Chunks (write-once payloads) on the HDD; the catalog in tablespace
# nvme, the database's default_tablespace (LOG.md 2026-10-09 (14)).
- ./pg:/var/lib/postgresql/data
- ${PG_NVME_DIR:-/var/lib/usenet-rebuild-catalog}:/var/lib/postgresql/nvme
# synchronous_commit = off is set with ALTER SYSTEM (postgresql.auto.conf in the data dir).
command:
- postgres
- -c
- shared_preload_libraries=pg_stat_statements
- -c
- shared_buffers=${PG_SHARED_BUFFERS:-2GB}
- -c
- max_wal_size=8GB
- -c
- checkpoint_timeout=15min
shm_size: 1g
stop_grace_period: 120s
healthcheck:
test: ['CMD-SHELL', 'pg_isready -U "$$POSTGRES_USER" -d "$$POSTGRES_DB"']
interval: 5s
retries: 30
migrate:
<<: *app
restart: 'no'
command: ['node', 'ace', 'migration:run', '--force']
volumes: []
depends_on:
postgres:
condition: service_healthy
# Catalog API, Newznab and the web interface.
web:
<<: *app
command: ['node', 'bin/server.js']
environment:
<<: *app-env
HTTP_ROUTES: public
ports:
- '3334:3334'
# The edge workers' API (leases, streams, batches), apart from the web
# interface: streams hold a connection up to an hour, batches of up to
# 256 MB are parsed in-process. Only the compose network reaches it.
node-api:
<<: *app
command: ['node', 'bin/server.js']
environment:
<<: *app-env
HTTP_ROUTES: node
PORT: 3335
# Prefetching (all NNTP connections), planning, the tail, merging, settling.
coordinator:
<<: *app
command: ['node', 'ace', 'coordinator:run']
environment:
<<: *app-env
NNTP_CONNECTIONS: ${NNTP_CONNECTIONS:-40}
# Phase 2's prober: reads the probe queue's articles over PROBE_CONNECTIONS
# connections of its own (next to the coordinator's 40 + 1; the account has 50).
prober:
<<: *app
command: ['node', 'ace', 'probe:run']
volumes: []
environment:
<<: *app-env
PROBE_CONNECTIONS: ${PROBE_CONNECTIONS:-6}
# The par2 merge: releases whose files one par2 set describes (what the prober read) become one. No NNTP.
merger:
<<: *app
command: ['node', 'ace', 'releases:merge']
volumes: []
# The Rust worker; it has no NNTP account and talks to node-api only.
# Stopped before node-api (a worker holding a stream keeps the server from
# exiting).
edge:
image: usenet-rebuild-edge:latest
build:
context: ./src
target: edge
restart: unless-stopped
command: ['--threads', '${EDGE_THREADS:-8}']
environment:
COORDINATOR_URL: http://node-api:3335
NODE_TOKEN: ${NODE_TOKEN}
stop_grace_period: 60s
depends_on:
node-api:
condition: service_started
# The TypeScript worker, for comparing: docker compose --profile edge-ts up -d edge-ts
edge-ts:
<<: *app
profiles: [edge-ts]
command: ['node', 'ace', 'edge:node', '--processes', '${EDGE_THREADS:-8}']
environment:
<<: *app-env
COORDINATOR_URL: http://node-api:3335
depends_on:
node-api:
condition: service_started
# One-off ace commands: docker compose run --rm ace releases:duplicates
ace:
<<: *app
profiles: [tools]
restart: 'no'
entrypoint: ['node', 'ace']
command: ['list']
networks:
default:
name: usenet-rebuild