MCPcopy Create free account
hub / github.com/PerpetualSoftware/pad / Stop

Method Stop

internal/server/server.go:357–395  ·  view source on GitHub ↗

Stop waits for all background goroutines started via goAsync to finish AND drains the rate-limiter cleanup goroutines spawned at construction time (BUG-851). Safe to call multiple times. Should be called before Store.Close() so in-flight DB writes don't race a closed connection (or worse, the SQLite

()

Source from the content-addressed store, hash-verified

355// Store.Close() so in-flight DB writes don't race a closed connection
356// (or worse, the SQLite -wal/-shm file removal in t.TempDir cleanup).
357func (s *Server) Stop() {
358 // Signal long-running background loops (orphan GC, etc.) to exit.
359 // Each loop registers itself on s.bg, so the Wait() below blocks
360 // until they actually finish and any in-flight goroutines drain.
361 s.stopOrphanGC()
362 // Yjs op-log prune sweeper (TASK-1309). Same lifecycle pattern;
363 // signals BEFORE Wait() so the goroutine sees the close and exits.
364 s.stopOpLogGC()
365 // Short-lived-credential reaper (PLAN-1933 DR-5 / TASK-1936). Same
366 // lifecycle pattern; signal BEFORE Wait() so the goroutine exits.
367 s.stopTokenReaper()
368 // Soft-deleted-workspace hard-purge sweeper (TASK-1966). Same
369 // lifecycle pattern; signal BEFORE Wait() so the goroutine exits.
370 s.stopWorkspacePurgeSweeper()
371 // MCP audit writer / sweeper run on s.bg too. Signal first so
372 // the workers see the close BEFORE Wait() blocks; without the
373 // signal Wait would hang forever on the writer's blocking
374 // queue receive.
375 s.stopMCPAuditWriter()
376 // MCP session tracker (TASK-1120) runs its sweeper on s.bg too.
377 // Order with the audit writer doesn't matter — both are
378 // independent goroutines; we just need the close BEFORE Wait().
379 s.stopMCPSessionTracker()
380 // Close the collab room manager BEFORE bg.Wait() so any in-flight
381 // op-log GC sweep (TASK-1309) blocked on a per-item lock behind
382 // an active Join can drain. collab.Close() tears down the Joins
383 // (their WS readLoops return, runConn unwinds, itemLocks
384 // release), which unblocks the GC's per-item PruneItemOpLogIfDormantBefore
385 // call. Without this ordering, Stop() can deadlock: GC waits on
386 // itemLock; Join holds itemLock until WS closes; WS only closes
387 // when collab.Close() runs; collab.Close() only runs after
388 // bg.Wait(); bg.Wait() never returns because GC is stuck.
389 // Per Codex review of TASK-1309 [P2]. nil-safe: collab is optional.
390 if s.collab != nil {
391 s.collab.Close()
392 }
393 s.bg.Wait()
394 s.rateLimiters.Stop() // nil-safe via the RateLimiters receiver guard
395}
396
397func New(s *store.Store) *Server {
398 rl := NewRateLimiters()

Callers 15

startWALCheckpointerMethod · 0.45
pollUntilSetupDoneFunction · 0.45
RunStdioMethod · 0.45
newPadServerFunction · 0.45
runMethod · 0.45
testServerFunction · 0.45
testServerPostgresFunction · 0.45

Calls 7

stopOrphanGCMethod · 0.95
stopOpLogGCMethod · 0.95
stopTokenReaperMethod · 0.95
stopMCPAuditWriterMethod · 0.95
stopMCPSessionTrackerMethod · 0.95
CloseMethod · 0.65