返回 DeepSeek-Reasonix
turn_autosave.go
根目录 / internal / control / turn_autosave.go
1 package control
2
3 import (
4 "context"
5 "log/slog"
6 "sync/atomic"
7 "time"
8 )
9
10 // midTurnSnapshotInterval is atomic (nanoseconds) so a test shrinking it
11 // cannot race a previous test's still-parking autosave goroutine.
12 var midTurnSnapshotInterval atomic.Int64
13
14 func init() { midTurnSnapshotInterval.Store(int64(30 * time.Second)) }
15
16 // autosaveWhileRunning snapshots the session periodically while a turn runs,
17 // so an abrupt kill (SSH drop, force-quit) loses at most one interval of a
18 // long turn instead of all of it (#3772). Session.Save copies under the lock
19 // and replaces the file atomically, so racing the turn's appends is safe.
20 // The same tick drives the stall watchdog, so silence is checked as often as
21 // progress is persisted.
22 func (c *Controller) autosaveWhileRunning(ctx context.Context) {
23 t := time.NewTicker(time.Duration(midTurnSnapshotInterval.Load()))
24 defer t.Stop()
25 for {
26 select {
27 case <-ctx.Done():
28 return
29 case <-t.C:
30 if err := c.snapshot(false, false, false); err != nil {
31 slog.Warn("controller: mid-turn snapshot", "err", err)
32 }
33 c.warnIfTurnStalled(time.Now())
34 }
35 }
36 }
37
37 lines GO