main.go: worker starts go through goWorker (V-575)

Seven copies of add one, go, defer done. The helper keeps the WaitGroup
registration next to the goroutine it counts, so a worker cannot be started
without shutdown waiting for it.

The UnlockFn goroutines keep the shape they had, wg and all.
This commit is contained in:
2026-08-06 01:29:24 +04:00
parent 01b47e3864
commit 4f7ad7d99a
+21 -43
View File
@@ -578,71 +578,39 @@ func run(args []string) error {
}
}
wg.Add(1)
go func() {
defer wg.Done()
goWorker(&wg, func() {
if err := srv.Serve(); err != nil && !errors.Is(err, net.ErrClosed) {
log.Printf("ipc serve: %v", err)
}
}()
})
log.Printf("mavend: ipc listening on %s", srv.Path())
if !locked && voiceW != nil {
wg.Add(1)
go func() {
defer wg.Done()
goWorker(&wg, func() {
if err := voiceW.server.Serve(); err != nil && !errors.Is(err, net.ErrClosed) {
log.Printf("voice serve: %v", err)
}
}()
})
log.Printf("mavend: voice listening on %s", voiceW.server.Addr())
}
if !locked {
wg.Add(1)
go func() {
defer wg.Done()
tl.run(ctx)
}()
wg.Add(1)
go func() {
defer wg.Done()
factWorker.run(ctx)
}()
goWorker(&wg, func() { tl.run(ctx) })
goWorker(&wg, func() { factWorker.run(ctx) })
if evalWorker != nil {
wg.Add(1)
go func() {
defer wg.Done()
evalWorker.run(ctx)
}()
goWorker(&wg, func() { evalWorker.run(ctx) })
}
if feedWkr != nil {
wg.Add(1)
go func() {
defer wg.Done()
feedWkr.run(ctx)
}()
goWorker(&wg, func() { feedWkr.run(ctx) })
}
if crawlWkr != nil {
wg.Add(1)
go func() {
defer wg.Done()
crawlWkr.run(ctx)
}()
goWorker(&wg, func() { crawlWkr.run(ctx) })
}
if voiceW != nil && voiceW.mcp != nil {
wg.Add(1)
go func() {
defer wg.Done()
voiceW.mcp.run(ctx)
}()
goWorker(&wg, func() { voiceW.mcp.run(ctx) })
}
if voiceW != nil && voiceW.home != nil {
wg.Add(1)
go func() {
defer wg.Done()
voiceW.home.run(ctx)
}()
goWorker(&wg, func() { voiceW.home.run(ctx) })
}
}
@@ -839,6 +807,16 @@ func wireTickLoop(st *store.Store, gatherer *loop.Gatherer, dispatcher *delivery
cfg.PatternProposals)
}
// goWorker starts run on its own goroutine and registers it with wg, so
// shutdown can wait for it inside workerGrace.
func goWorker(wg *sync.WaitGroup, run func()) {
wg.Add(1)
go func() {
defer wg.Done()
run()
}()
}
// wireRules builds the nudge rule set, minus anything config turned off. The
// drop is logged because a rule vanishing silently is indistinguishable from a
// rule that is broken, and the next person to wonder why she stopped nudging