feat(gpu-box): news-ingester migrated, Mini compose drops the service block

Phase 2f-2. RSS/Atom ingester (15-min tick → mana_platform.news.curated_articles)
moved to GPU-Box. Service has zero hot-path coupling, all the writes go
cross-LAN to Mini-postgres analog to the Glitchtip pattern.

Two implementation gotchas worth recording:

1. cross-arch image transfer doesn't work. Saved news-ingester:local
   from the Mini (Apple M4 → linux/arm64), tried `docker load` on the
   GPU-Box (linux/amd64) and got 'exec format error' on every restart.
   Native build on the GPU-Box was the only path forward.

2. The original services/news-ingester/Dockerfile assumes
   pnpm-workspace state from prior builds (no COPY for packages/shared-rss
   in the build context). Fresh builds error with
   ERR_PNPM_WORKSPACE_PKG_NOT_FOUND.

Workaround: a GPU-Box-specific Dockerfile at infrastructure/news-ingester/
that vendors shared-rss into the build via a workspace:* → file:ref
sed swap. Build context is the repo root (sparse-clone provides
packages/shared-rss + services/news-ingester). The Mini-side Dockerfile
stays untouched so existing CD builds aren't disturbed.

Mini-side: container stopped + removed from docker-compose.macmini.yml,
running container count 44 → 39.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Till JS 2026-05-07 16:27:45 +02:00
parent 71ec5e7123
commit b03165ce97
3 changed files with 51 additions and 33 deletions

View file

@ -1436,39 +1436,6 @@ services:
# from the same table to serve /api/v1/news/feed; user reading lists
# remain client-side in the unified Mana app's local IndexedDB.
news-ingester:
build:
context: services/news-ingester
dockerfile: Dockerfile
image: news-ingester:local
container_name: news-ingester
restart: always
mem_limit: 256m
depends_on:
postgres: { condition: service_healthy }
environment:
TZ: Europe/Berlin
PORT: 3066
DATABASE_URL: postgresql://postgres:${POSTGRES_PASSWORD:-mana123}@postgres:5432/mana_platform
TICK_INTERVAL_MS: "900000"
RUN_ON_STARTUP: "true"
ports:
- "3066:3066"
healthcheck:
test: ["CMD", "bun", "-e", "fetch('http://127.0.0.1:3066/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"]
interval: 120s
timeout: 10s
retries: 3
start_period: 30s
# ============================================
# Games
# ============================================
# whopixels was removed 2026-04-09 — its core mechanic (LLM-driven
# historical figure guessing) lives now as the `who` module inside
# apps/mana/apps/web. The standalone Phaser/Node container is gone;
# see docs/WHO_MODULE.md for the migration rationale.
volumes:
redis_data:
name: mana-redis-data

View file

@ -493,6 +493,36 @@ services:
# lebt jetzt in mana-monorepo's infrastructure/verdaccio/config.yaml,
# sparse-clone trägt das Verzeichnis auf der GPU-Box ein.
# ============================================
# ============================================
# Phase 2f-2 — news-ingester (2026-05-07)
# Background article-ingester — Bun-Service mit 15-min-Tick. Schreibt
# in Mini-Postgres mana_platform via LAN. Reine Background-Last,
# null Hot-Path-Coupling.
# ============================================
news-ingester:
# GPU-Box-spezifischer Build (services/news-ingester/Dockerfile ist
# nicht workspace-aware; der hier vendored shared-rss als file: ref).
# Cross-arch: GPU-Box ist x86_64, Mini ist arm64 — Image-Transfer
# via docker save/load würde "exec format error" werfen.
build:
context: /srv/mana/source
dockerfile: infrastructure/news-ingester/Dockerfile
image: news-ingester:gpu-box
container_name: news-ingester
restart: unless-stopped
environment:
TZ: Europe/Berlin
PORT: 3066
DATABASE_URL: postgresql://postgres:${POSTGRES_PASSWORD}@192.168.178.131:5432/mana_platform
TICK_INTERVAL_MS: '900000'
RUN_ON_STARTUP: 'true'
healthcheck:
test: ['CMD', 'bun', '-e', "fetch('http://127.0.0.1:3066/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"]
interval: 120s
timeout: 10s
retries: 3
start_period: 30s
verdaccio:
image: verdaccio/verdaccio:6
container_name: mana-verdaccio

View file

@ -0,0 +1,21 @@
# News-ingester for GPU-Box — workspace-aware (vendors shared-rss).
# Context: repo root. Use this Dockerfile when deploying news-ingester
# on the GPU-Box (the one in services/news-ingester/Dockerfile is
# Mini-side and assumes the cached pnpm-workspace state).
FROM oven/bun:1 AS production
WORKDIR /app
COPY packages/shared-rss ./packages/shared-rss
COPY services/news-ingester/package.json ./services/news-ingester/
COPY services/news-ingester/src ./services/news-ingester/src
COPY services/news-ingester/tsconfig.json services/news-ingester/drizzle.config.ts ./services/news-ingester/
WORKDIR /app/services/news-ingester
RUN sed -i 's|"@mana/shared-rss": "workspace:\*"|"@mana/shared-rss": "file:../../packages/shared-rss"|' package.json && \
bun install
EXPOSE 3066
HEALTHCHECK --interval=60s --timeout=10s --start-period=30s --retries=3 \
CMD bun -e "fetch('http://localhost:3066/health').then(r => process.exit(r.ok ? 0 : 1)).catch(() => process.exit(1))"
CMD ["bun", "run", "src/index.ts"]