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:
| Bot | Funktion | Port |
|---|---|---|
| matrix-mana-bot | Gateway: AI Chat + Todo + Calendar + Clock + Voice | 4010 |
| matrix-ollama-bot | LLM Chat (Ollama) | 4011 |
| matrix-stats-bot | System-Statistiken | 4012 |
| matrix-project-doc-bot | Projekt-Dokumentation | 4013 |
| matrix-todo-bot | Aufgabenverwaltung | 4014 |
| matrix-calendar-bot | Kalender | 4015 |
| matrix-nutriphi-bot | Ernรคhrungstracking | 4016 |
| matrix-zitare-bot | Zitate & Inspiration | 4017 |
| matrix-clock-bot | Timer, Alarme, Weltuhren | 4018 |
| matrix-tts-bot | Text-to-Speech | 4019 |
| matrix-stt-bot | Speech-to-Text | 4021 |
| matrix-onboarding-bot | User Onboarding | 4020 |
| matrix-planta-bot | Pflanzenpflege | 4022 |
| + 8 weitere | Chat, Contacts, ManaDeck, Picture, Presi, Questions, Skilltree, Storage | โ |
Ressourcenverbrauch vorher
| Metrik | Wert |
|---|---|
| Prozesse | 21 (+ 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 Container | 13 aktive Container |
| Ports belegt | 4010-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 Jobs | 10 separate Docker-Build Jobs |
Die Lรถsung: Go Binary mit Plugin-Architektur
Architektur-Entscheidungen
| Entscheidung | Gewรคhlt | Alternativen verworfen |
|---|---|---|
| Sprache | Go 1.25 | NestJS Monolith, Rust |
| Matrix SDK | mautrix-go | Raw CS API |
| Plugin-System | Compile-time Interfaces | Go plugin Package, hashicorp/go-plugin |
| Identities | Ein mautrix.Client pro Plugin | Shared Client mit Routing |
| Sessions | In-Memory + Redis | Nur In-Memory |
| Config | Environment Variables | YAML 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
| Metrik | Vorher (NestJS) | Nachher (Go) | Ersparnis |
|---|---|---|---|
| Prozesse | 21 | 1 | -95% |
| RAM | ~2.1 GB | ~30 MB | -98.6% |
| Docker Images | ~4.2 GB (21ร200MB) | 7.5 MB | -99.8% |
| Docker Container | 13 | 1 | -92% |
| Ports | 13 (4010-4022) | 1 (4000) | -92% |
| Startup | ~5 Min | <1 Sek | -99% |
| Binary | โ | 8.6 MB | Single file |
Codebase
| Metrik | Vorher (NestJS) | Nachher (Go) | Delta |
|---|---|---|---|
| Service-Verzeichnisse | 21 + 2 Packages | 1 | -22 |
| Source Files | ~400+ (TS) | 39 (Go) | -90% |
| Test Files | verteilt | 5 | โ |
| Source Lines | ~15.000+ | 7.293 | -51% |
| Test Lines | โ | 327 | โ |
| Dependencies | 21 ร package.json | 1 ร go.mod (4 deps) | -99% |
| CI Build Jobs | 10 | 1 | -90% |
Docker Compose
| Metrik | Vorher | Nachher |
|---|---|---|
| Bot-Services | 13 Definitionen | 1 Definition |
| YAML Zeilen | ~475 | ~90 |
| Environment Vars | verteilt รผber 13 Services | zentralisiert in 1 Service |
| Volume Mounts | 13 ร matrix_bots_data | 1 ร 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:
internal/plugins/mybot/mybot.goerstellenplugin.Register("mybot", ...)ininit()- Import in
main.go
Feature-Vollstรคndigkeit der Plugins
Voll portiert (mit allen Commands)
| Plugin | Commands | Features |
|---|---|---|
| todo | !todo, !list, !today, !inbox, !done, !delete, !projekte | German date parsing, Priority, Projects |
| calendar | !heute, !morgen, !woche, !termine, !termin, !lรถschen, !kalender | Event creation, Date parsing |
| clock | !timer, !stop, !resume, !reset, !timers, !alarm, !alarme, !zeit | Duration parsing (25m, 1h30m) |
| contacts | !kontakte, !suche, !favoriten, !kontakt, !neu, !edit, !fav, !delete | 16 editierbare Felder, Number-References |
| zitare | !zitat, !heute, !suche, !kategorie, !kategorien, !motivation, !favorit, !favoriten, !listen | Categories, Favorites, Lists |
| planta | !pflanzen, !pflanze, !neu, !giessen, !fรคllig, !historie, !intervall, !edit, !delete | Watering schedule, Health tracking |
| ollama | AI Chat, !models, !model, !clear, !all, !mode | Chat history, System prompts, Model comparison |
| stt | AudioโText, !language, !model, !status | Whisper/Voxtral, Language selection |
| tts | TextโAudio, !voice, !voices, !speed, !status | Voice selection, Speed control |
| gateway | Alles oben + !morning, Voice pipeline | Composite: 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:
- Matrix
/syncempfรคngt Event - Runtime filtert: eigene Messages, Bot-Messages, Edits
- Room-Allowlist-Check
!login/!logoutglobal abgefangen- Text โ Plugin.HandleTextMessage()
- 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
| Was | Menge |
|---|---|
services/matrix-*-bot/ | 21 Verzeichnisse |
packages/matrix-bot-common/ | 1 Package (~30 Dateien) |
packages/bot-services/ | 1 Package (~50 Dateien) |
| Docker-Compose Bot-Services | 13 Service-Definitionen (~475 Zeilen) |
| CI Build Jobs | 10 Jobs (~300 Zeilen) |
| CI Change Detection | 10 Blรถcke + Outputs (~100 Zeilen) |
| Root package.json Scripts | 10 Legacy-Bot-Scripts |
| Deploy Scripts | setup-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-botService in docker-compose - Ein
build-mana-matrix-botCI Job - Historische Devlog-Referenzen (als Dokumentation)
CI/CD
GitHub Actions
- CI:
build-mana-matrix-botJob 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
| Aspekt | Bewertung |
|---|---|
| RAM-Ersparnis | ~2 GB frei auf dem Mac Mini |
| Disk-Ersparnis | ~4.2 GB Docker Images weniger |
| Wartbarkeit | 1 Service statt 21 |
| Deployment | 1 Container statt 13 |
| Startup | <1s statt ~5 Min |
| Erweiterbarkeit | Neues 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.