refactor: ein Binary — talk startet den Daemon selbst, talkd und Degraded Mode entfallen
Zwei Binaries erzeugten den halben Komplexitätsballast: Degraded Mode mit Lock-Datei und Stale-Lock-Race, „läuft talkd?", Autostart-Konfiguration je OS, doppelte Chain-Konstruktion in cmd/talk und cmd/talkd — und der Degraded Mode kannte weder Rate-Limit noch Ruhezeiten. Jetzt: - internal/speak: der eine Sprech-Kern (Config + Sink + Kette → Ansage); Daemon und Direkt-Pfad benutzen ihn, es gibt keine zweite Zusammensetzung der Kette mehr. - internal/daemon: Run (der bisherige talkd-Kern), Spawn (detached per Setsid bzw. DETACHED_PROCESS, stdout/stderr → daemon.log), PID-Datei daemon.pid, Shutdown-Trigger. - `talk daemon run|start|stop`: Vordergrund (systemd/launchd), expliziter Hintergrund-Start, Stop per POST /shutdown — stop wartet, bis HTTP weg und die PID-Datei gelöscht ist (Prozess wirklich beendet). - Autostart: say/wrap starten den Daemon beim ersten Sprechbefehl selbst (daemon.autostart, Default an; Env TALK_AUTOSTART). Verliert ein paralleler Aufruf das Port-Rennen, erkennt er das am Kind-Ende und nutzt den Daemon des anderen — kein Timeout-Warten. - Direkt-Pfad statt Degraded Mode: ohne erreichbaren oder startbaren Daemon spricht talk direkt (Mute respektiert, kein Lock, Hinweis + Grund + Log-Pfad auf stderr). Steuerbefehle starten den Daemon bewusst nicht; `talk status` zeigt „läuft nicht" (Exit 1). - cmd/talkd und cmd/talk/degraded.go entfernt; README-Daemon-Abschnitt neu. Tests: Harness baut nur noch talk und startet `talk daemon run`; TALK_AUTOSTART=false als Grundausstattung aller Tests (kein Test hinterlässt Daemons), autostart_test.go schaltet es bewusst an: Autostart beim ersten say, Idempotenz, paralleler Start in EINE Queue, expliziter start/stop, Port fremd belegt → Direkt-Pfad ohne Timeout. Cross-Compile aller sechs Targets mit CGO_ENABLED=0 verifiziert. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
b86632006e
commit
bc26a73aeb
29 files changed
+1145
-584
No files matched your search
+6
-6
@@ -147,22 +147,22 @@ func TestWrapWait(t *testing.T) {
|
||||
waitStatusIdle(t, d, 3*time.Second)
|
||||
}
|
||||
|
||||
// TestWrapDegradedMode: Daemon tot → Ansage im Degraded Mode (Lock-Datei,
|
||||
// direkt gegen den Fake), und der Exit-Code des Befehls bleibt trotzdem.
|
||||
func TestWrapDegradedMode(t *testing.T) {
|
||||
// TestWrapOhneDaemon: Daemon tot, Autostart aus → Ansage direkt gegen den
|
||||
// Fake, und der Exit-Code des Befehls bleibt trotzdem.
|
||||
func TestWrapOhneDaemon(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
fake := newFakeProvider(t, 0)
|
||||
env := daemonEnv(root, 1, fake.srv.URL, nil) // Port 1: Daemon garantiert tot
|
||||
|
||||
res := runTalk(t, env, "wrap", "--", "sh", "-c", "exit 3")
|
||||
if res.code != 3 {
|
||||
t.Fatalf("talk wrap (Degraded): Exit %d, want 3 (Befehls-Code gewinnt)", res.code)
|
||||
t.Fatalf("talk wrap (direkt): Exit %d, want 3 (Befehls-Code gewinnt)", res.code)
|
||||
}
|
||||
hits := fake.waitCompleted(t, 1)
|
||||
if hits[0].Text != "sh fehlgeschlagen, Code 3." {
|
||||
t.Errorf("Ansage = %q, want %q", hits[0].Text, "sh fehlgeschlagen, Code 3.")
|
||||
}
|
||||
if !strings.Contains(res.stderr, "Degraded Mode") {
|
||||
t.Errorf("stderr = %q, will Degraded-Hinweis (nichts bricht still)", res.stderr)
|
||||
if !strings.Contains(res.stderr, "spreche direkt") {
|
||||
t.Errorf("stderr = %q, will Direkt-Hinweis (nichts bricht still)", res.stderr)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user