返回 DeepSeek-Reasonix
session_maintenance_events.go
根目录 / internal / control / session_maintenance_events.go
1 package control
2
3 import (
4 "context"
5 "encoding/json"
6 "errors"
7 "fmt"
8
9 "reasonix/internal/event"
10 "reasonix/internal/provider"
11 "reasonix/internal/session"
12 )
13
14 // persistMaintenanceOperation has its own durability barrier: maintenance is
15 // deliberately outside a turn, so the ordinary TurnDone flush cannot own it.
16 func (c *Controller) persistMaintenanceOperation(e event.Event) error {
17 events, err := sessionMaintenanceEvents(e)
18 if err != nil {
19 return err
20 }
21 if !c.sessionEventCommitAllowed() {
22 return session.ErrStaleExecution
23 }
24 store := c.sessionEventStore()
25 if store == nil {
26 if c.sessionEngineEnabled() {
27 return session.ErrSessionNotRunning
28 }
29 return nil
30 }
31 op := e.SessionOperation
32 c.turnEvents.commitMu.Lock()
33 commit, err := c.appendSessionBatch(context.Background(), store, session.Batch{
34 OperationID: fmt.Sprintf("session-maintenance:%s:%d", op.OperationID, op.OperationRevision), Events: events,
35 })
36 c.turnEvents.commitMu.Unlock()
37 if err != nil {
38 return err
39 }
40 receipt, err := store.Flush(context.Background())
41 if err != nil {
42 return err
43 }
44 if receipt.DurableSequence < commit.LastSequence() {
45 return fmt.Errorf("maintenance operation is not durable through sequence %d", commit.LastSequence())
46 }
47 return nil
48 }
49
50 // sessionMaintenanceEvents persists one replaceable display record. The
51 // diagnostic is optional, excluded from Projection.ModelMessages, and safe for
52 // older readers to ignore.
53 func sessionMaintenanceEvents(e event.Event) ([]session.Event, error) {
54 if e.SessionOperation == nil || e.SessionOperation.OperationID == "" {
55 return nil, errors.New("session operation has no identity")
56 }
57 content, err := json.Marshal(e.SessionOperation)
58 if err != nil {
59 return nil, err
60 }
61 record, err := json.Marshal(provider.Message{
62 ID: "maintenance:" + e.SessionOperation.OperationID,
63 Role: provider.Role("compaction"), Content: string(content),
64 })
65 if err != nil {
66 return nil, err
67 }
68 payload, err := json.Marshal(map[string]any{
69 "type": "session-maintenance-v1", "displayRecord": json.RawMessage(record),
70 })
71 if err != nil {
72 return nil, err
73 }
74 return []session.Event{{Kind: "diagnostic", Optional: true, Payload: payload}}, nil
75 }
76
76 lines GO