Zum Hauptinhalt springen

Zurรผck zum Devlog

Freitag, 27. Mรคrz 2026

Infrastructure

12 min Lesezeit

Matrix Bot Konsolidierung: 21 NestJS-Bots โ†’ 1 Go Binary

Komplette Neuentwicklung des Matrix-Bot-Systems in Go mit Plugin-Architektur. 21 separate NestJS-Prozesse (~2.1 GB RAM, ~4.2 GB Docker Images) ersetzt durch ein einziges Go-Binary (8.6 MB, ~30 MB RAM). Inklusive Redis Sessions, CI/CD, Docker-Migration und Legacy-Cleanup.

T

Till Schneider

Autor

Einer der grรถรŸten Architektur-Umbauten im ManaCore-Monorepo: 21 separate NestJS Matrix-Bot-Prozesse komplett ersetzt durch ein einziges Go-Binary mit Plugin-Architektur. Dazu Legacy-Code aufgerรคumt, CI/CD migriert und Docker-Compose aktualisiert.


Das Problem: 21 NestJS-Prozesse

Jeder Matrix-Bot lief als eigenstรคndiger NestJS-Service mit eigenem Docker-Container:

BotFunktionPort
matrix-mana-botGateway: AI Chat + Todo + Calendar + Clock + Voice4010
matrix-ollama-botLLM Chat (Ollama)4011
matrix-stats-botSystem-Statistiken4012
matrix-project-doc-botProjekt-Dokumentation4013
matrix-todo-botAufgabenverwaltung4014
matrix-calendar-botKalender4015
matrix-nutriphi-botErnรคhrungstracking4016
matrix-zitare-botZitate & Inspiration4017
matrix-clock-botTimer, Alarme, Weltuhren4018
matrix-tts-botText-to-Speech4019
matrix-stt-botSpeech-to-Text4021
matrix-onboarding-botUser Onboarding4020
matrix-planta-botPflanzenpflege4022
+ 8 weitereChat, Contacts, ManaDeck, Picture, Presi, Questions, Skilltree, Storageโ€”

Ressourcenverbrauch vorher

MetrikWert
Prozesse21 (+ 13 in docker-compose)
RAM gesamt~2.1 GB (je ~80-120 MB pro Bot)
Docker Images~21 ร— 200 MB = ~4.2 GB Disk
Docker Container13 aktive Container
Ports belegt4010-4022 (13 Ports)
Startup-Zeit~30s pro Bot, ~5 Min gesamt
Source Code~21 Services + 2 Shared Packages
node_modules~21 ร— node_modules Kopien
CI Build Jobs10 separate Docker-Build Jobs

Die Lรถsung: Go Binary mit Plugin-Architektur

Architektur-Entscheidungen

EntscheidungGewรคhltAlternativen verworfen
SpracheGo 1.25NestJS Monolith, Rust
Matrix SDKmautrix-goRaw CS API
Plugin-SystemCompile-time InterfacesGo plugin Package, hashicorp/go-plugin
IdentitiesEin mautrix.Client pro PluginShared Client mit Routing
SessionsIn-Memory + RedisNur In-Memory
ConfigEnvironment VariablesYAML Config

Warum Go?

  • RAM: Go-Prozesse brauchen ~10-30 MB statt ~100 MB pro NestJS-Instanz
  • Binary: Ein statisch kompiliertes Binary, kein node_modules
  • Concurrency: 21 Matrix /sync-Loops als Goroutines (quasi kostenlos)
  • Startup: <1 Sekunde fรผr alle 21 Plugins
  • Docker: Alpine-basiert, 7.5 MB statt ~200 MB pro Image
  • Konsistenz: Passt zum bestehenden Go Sync-Server (mana-sync)

Projektstruktur

services/mana-matrix-bot/          # 50 Dateien, 7.620 Zeilen Go
โ”œโ”€โ”€ cmd/server/main.go             # Entry Point (21 Plugin-Imports)
โ”œโ”€โ”€ internal/
โ”‚   โ”œโ”€โ”€ config/config.go           # Env-Config mit Legacy-Token-Support
โ”‚   โ”œโ”€โ”€ runtime/
โ”‚   โ”‚   โ”œโ”€โ”€ runtime.go             # Plugin-Orchestrator, Sync-Loops, Event-Routing
โ”‚   โ”‚   โ””โ”€โ”€ health.go              # Health + Prometheus Metrics
โ”‚   โ”œโ”€โ”€ matrix/
โ”‚   โ”‚   โ”œโ”€โ”€ client.go              # mautrix-go Wrapper
โ”‚   โ”‚   โ”œโ”€โ”€ markdown.go            # Markdownโ†’HTML (Port von TypeScript)
โ”‚   โ”‚   โ””โ”€โ”€ types.go               # IsBot, IsEdit, IsText Guards
โ”‚   โ”œโ”€โ”€ plugin/
โ”‚   โ”‚   โ”œโ”€โ”€ plugin.go              # Plugin Interface + SessionManager
โ”‚   โ”‚   โ”œโ”€โ”€ registry.go            # Compile-time Registration
โ”‚   โ”‚   โ”œโ”€โ”€ command.go             # !command Router
โ”‚   โ”‚   โ””โ”€โ”€ keyword.go             # Keyword-Detector (DE/EN)
โ”‚   โ”œโ”€โ”€ session/
โ”‚   โ”‚   โ”œโ”€โ”€ session.go             # In-Memory Store
โ”‚   โ”‚   โ””โ”€โ”€ redis.go               # Redis Store (Cross-Bot SSO)
โ”‚   โ”œโ”€โ”€ services/
โ”‚   โ”‚   โ”œโ”€โ”€ backend.go             # Generic HTTP Client
โ”‚   โ”‚   โ”œโ”€โ”€ voice.go               # STT/TTS Client
โ”‚   โ”‚   โ”œโ”€โ”€ auth.go                # Login via mana-core-auth
โ”‚   โ”‚   โ””โ”€โ”€ credit.go              # Credit Balance & Consumption
โ”‚   โ””โ”€โ”€ plugins/                   # 21 Plugin-Verzeichnisse
โ”‚       โ”œโ”€โ”€ gateway/               # Composite: AI + Todo + Cal + Clock + Voice
โ”‚       โ”œโ”€โ”€ todo/                  # Vollstรคndig: !todo, !list, !done, !delete, etc.
โ”‚       โ”œโ”€โ”€ calendar/              # !heute, !morgen, !woche, !termine
โ”‚       โ”œโ”€โ”€ clock/                 # !timer, !stop, !alarm, !zeit
โ”‚       โ”œโ”€โ”€ contacts/              # !kontakte, !suche, !favoriten, !edit
โ”‚       โ”œโ”€โ”€ zitare/                # !zitat, !suche, !kategorie, !favoriten
โ”‚       โ”œโ”€โ”€ planta/                # !pflanzen, !giessen, !fรคllig, !historie
โ”‚       โ”œโ”€โ”€ ollama/                # AI Chat, !models, !all, !mode
โ”‚       โ”œโ”€โ”€ stt/                   # Audioโ†’Text, !language, !model
โ”‚       โ”œโ”€โ”€ tts/                   # Textโ†’Audio, !voice, !speed
โ”‚       โ””โ”€โ”€ ... (11 weitere)
โ”œโ”€โ”€ Dockerfile                     # Multi-stage Alpine Build
โ”œโ”€โ”€ go.mod / go.sum
โ””โ”€โ”€ CLAUDE.md

Vorher โ†’ Nachher: Die Zahlen

Ressourcen

MetrikVorher (NestJS)Nachher (Go)Ersparnis
Prozesse211-95%
RAM~2.1 GB~30 MB-98.6%
Docker Images~4.2 GB (21ร—200MB)7.5 MB-99.8%
Docker Container131-92%
Ports13 (4010-4022)1 (4000)-92%
Startup~5 Min<1 Sek-99%
Binaryโ€”8.6 MBSingle file

Codebase

MetrikVorher (NestJS)Nachher (Go)Delta
Service-Verzeichnisse21 + 2 Packages1-22
Source Files~400+ (TS)39 (Go)-90%
Test Filesverteilt5โ€”
Source Lines~15.000+7.293-51%
Test Linesโ€”327โ€”
Dependencies21 ร— package.json1 ร— go.mod (4 deps)-99%
CI Build Jobs101-90%

Docker Compose

MetrikVorherNachher
Bot-Services13 Definitionen1 Definition
YAML Zeilen~475~90
Environment Varsverteilt รผber 13 Serviceszentralisiert in 1 Service
Volume Mounts13 ร— matrix_bots_data1 ร— matrix_bots_data

Plugin Interface

Jedes Plugin implementiert ein minimales Interface:

type Plugin interface {
    Name() string
    Init(ctx context.Context, cfg PluginConfig) error
    HandleTextMessage(ctx context.Context, mc *MessageContext) error
    Commands() []CommandDef
}

// Optional: Audio und Image Handler
type AudioHandler interface {
    HandleAudioMessage(ctx context.Context, mc *MessageContext, audioData []byte) error
}

Neues Plugin hinzufรผgen = 3 Schritte:

  1. internal/plugins/mybot/mybot.go erstellen
  2. plugin.Register("mybot", ...) in init()
  3. Import in main.go

Feature-Vollstรคndigkeit der Plugins

Voll portiert (mit allen Commands)

PluginCommandsFeatures
todo!todo, !list, !today, !inbox, !done, !delete, !projekteGerman date parsing, Priority, Projects
calendar!heute, !morgen, !woche, !termine, !termin, !lรถschen, !kalenderEvent creation, Date parsing
clock!timer, !stop, !resume, !reset, !timers, !alarm, !alarme, !zeitDuration parsing (25m, 1h30m)
contacts!kontakte, !suche, !favoriten, !kontakt, !neu, !edit, !fav, !delete16 editierbare Felder, Number-References
zitare!zitat, !heute, !suche, !kategorie, !kategorien, !motivation, !favorit, !favoriten, !listenCategories, Favorites, Lists
planta!pflanzen, !pflanze, !neu, !giessen, !fรคllig, !historie, !intervall, !edit, !deleteWatering schedule, Health tracking
ollamaAI Chat, !models, !model, !clear, !all, !modeChat history, System prompts, Model comparison
sttAudioโ†’Text, !language, !model, !statusWhisper/Voxtral, Language selection
ttsTextโ†’Audio, !voice, !voices, !speed, !statusVoice selection, Speed control
gatewayAlles oben + !morning, Voice pipelineComposite: AI + Todo + Calendar + Clock + Voice

Skeleton (Grundgerรผst mit !help, !status)

stats, chat, manadeck, nutriphi, picture, presi, questions, skilltree, storage, projectdoc, onboarding


Runtime-Architektur

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                    main.go                       โ”‚
โ”‚   21 Plugin-Imports โ†’ init() Registration        โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                   Runtime                        โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”         โ”‚
โ”‚  โ”‚ Plugin 1โ”‚  โ”‚ Plugin 2โ”‚  โ”‚Plugin 21โ”‚  ...     โ”‚
โ”‚  โ”‚ @mana-  โ”‚  โ”‚ @todo-  โ”‚  โ”‚ @tts-   โ”‚         โ”‚
โ”‚  โ”‚  bot    โ”‚  โ”‚  bot    โ”‚  โ”‚  bot    โ”‚         โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”˜         โ”‚
โ”‚       โ”‚            โ”‚            โ”‚                โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”         โ”‚
โ”‚  โ”‚mautrix  โ”‚  โ”‚mautrix  โ”‚  โ”‚mautrix  โ”‚         โ”‚
โ”‚  โ”‚Client 1 โ”‚  โ”‚Client 2 โ”‚  โ”‚Client 21โ”‚         โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”˜         โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚       โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                โ”‚
โ”‚              Matrix /sync                        โ”‚
โ”‚         (21 Goroutines, ~0 RAM)                  โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚  Health :4000   โ”‚  Sessions (Redis/Memory)       โ”‚
โ”‚  Metrics        โ”‚  Auth Client โ†’ mana-core-auth  โ”‚
โ”‚  Login/Logout   โ”‚  Credit Client                 โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Event-Flow:

  1. Matrix /sync empfรคngt Event
  2. Runtime filtert: eigene Messages, Bot-Messages, Edits
  3. Room-Allowlist-Check
  4. !login/!logout global abgefangen
  5. Text โ†’ Plugin.HandleTextMessage()
  6. Audio โ†’ Plugin.HandleAudioMessage() (wenn implementiert)

Globale Features

Login/Logout (Runtime-Level)

User: !login [email protected] meinpasswort
Bot:  โœ… Angemeldet als [email protected]

User: !logout
Bot:  โœ… Abgemeldet.

Wird im Runtime abgefangen, bevor es an Plugins geht. Token in Redis gespeichert โ†’ alle Plugins haben sofort Zugriff.

Redis Sessions

Sessions persistent รผber Container-Restarts. Alle 21 Plugins teilen sich den Session-Store:

Redis Key: mana-bot:session:token:@user:mana.how
Value:     {token: "eyJ...", expires_at: "2026-03-28T..."}

Legacy Cleanup

Gelรถscht

WasMenge
services/matrix-*-bot/21 Verzeichnisse
packages/matrix-bot-common/1 Package (~30 Dateien)
packages/bot-services/1 Package (~50 Dateien)
Docker-Compose Bot-Services13 Service-Definitionen (~475 Zeilen)
CI Build Jobs10 Jobs (~300 Zeilen)
CI Change Detection10 Blรถcke + Outputs (~100 Zeilen)
Root package.json Scripts10 Legacy-Bot-Scripts
Deploy Scriptssetup-mana-bot.sh, deploy-mana-bot.sh
Netto-47.222 Zeilen gelรถscht, +8.665 hinzugefรผgt

Was bleibt

  • services/mana-matrix-bot/ โ€” Der Go-Service
  • Ein mana-matrix-bot Service in docker-compose
  • Ein build-mana-matrix-bot CI Job
  • Historische Devlog-Referenzen (als Dokumentation)

CI/CD

GitHub Actions

  • CI: build-mana-matrix-bot Job mit Docker Multi-Platform Build (amd64 + arm64)
  • CD: Auto-Deploy bei Changes in services/mana-matrix-bot/
  • Change Detection: Nur Go-Service, keine Shared-Package-Dependencies mehr

Deployment

ssh mana-server
cd ~/projects/manacore-monorepo && git pull
./scripts/mac-mini/build-app.sh mana-matrix-bot
curl http://localhost:4000/health
# โ†’ {"status":"ok","plugins":["todo","calendar",...],"count":21}

Fazit

AspektBewertung
RAM-Ersparnis~2 GB frei auf dem Mac Mini
Disk-Ersparnis~4.2 GB Docker Images weniger
Wartbarkeit1 Service statt 21
Deployment1 Container statt 13
Startup<1s statt ~5 Min
ErweiterbarkeitNeues Plugin = 1 Go-Datei + Import
Codebase-47.222 Zeilen, netto -38.557 Zeilen sauberer

Die 2 GB RAM-Ersparnis auf dem Mac Mini sind besonders wertvoll โ€” das ist Platz fรผr 2-3 weitere Web-Apps oder ein grรถรŸeres Ollama-Modell.

Tags

#go #matrix #bots #performance #infrastructure #docker #consolidation #plugin-architecture #ci-cd #cleanup