| 1 | package control |
| 2 | |
| 3 | import ( |
| 4 | "context" |
| 5 | "errors" |
| 6 | "fmt" |
| 7 | "log/slog" |
| 8 | |
| 9 | "reasonix/internal/event" |
| 10 | ) |
| 11 | |
| 12 | func (c *Controller) prepareTurnAdmission(body func(context.Context) error) func(context.Context) error { |
| 13 | return c.prepareTurnAdmissionWithGoalRound(context.Background(), body, nil) |
| 14 | } |
| 15 | |
| 16 | func (c *Controller) prepareTurnAdmissionWithGoalRound(admissionCtx context.Context, body func(context.Context) error, goalRound *goalRoundReservation) func(context.Context) error { |
| 17 | if admissionCtx == nil { |
| 18 | admissionCtx = context.Background() |
| 19 | } |
| 20 | admissionErr := c.turnEventLedgerError() |
| 21 | ledger := c.turnEventLedger() |
| 22 | if admissionErr == nil && goalRound != nil && ledger == nil { |
| 23 | admissionErr = errors.New("goal round admission requires the v3 turn ledger") |
| 24 | } |
| 25 | if admissionErr == nil && ledger != nil { |
| 26 | if ledger.CurrentStatus() == event.TurnRecoveryRequired { |
| 27 | admissionErr = ErrRecoveryRequired |
| 28 | } else if id, err := ledger.Begin(); err != nil { |
| 29 | admissionErr = err |
| 30 | } else { |
| 31 | c.mu.Lock() |
| 32 | c.turns.turnID = id |
| 33 | c.mu.Unlock() |
| 34 | if err := c.emitTurnEventChecked(event.Event{Kind: event.TurnStatusChanged, Status: event.TurnQueued}); err != nil { |
| 35 | admissionErr = err |
| 36 | } else if goalRound != nil { |
| 37 | admissionErr = c.commitGoalRoundAdmission(goalRound) |
| 38 | } else if err := c.emitTurnEventChecked(event.Event{Kind: event.TurnStarted, Status: event.TurnInProgress}); err != nil { |
| 39 | admissionErr = err |
| 40 | } else if c.executor != nil { |
| 41 | // The committed host turn boundary owns todo lifetime. The executor |
| 42 | // repeats this reset on entry for controller-less clients. |
| 43 | c.executor.BeginTurnTodoState() |
| 44 | } |
| 45 | } |
| 46 | } |
| 47 | if admissionErr == nil { |
| 48 | admissionErr = c.flushSubmissionAdmission(admissionCtx) |
| 49 | } |
| 50 | if admissionErr == nil { |
| 51 | if c.executor != nil && goalRound != nil { |
| 52 | c.executor.BeginTurnTodoState() |
| 53 | } |
| 54 | return body |
| 55 | } |
| 56 | slog.Error("controller: persist turn admission", "err", admissionErr) |
| 57 | return func(context.Context) error { return fmt.Errorf("persist turn admission: %w", admissionErr) } |
| 58 | } |
| 59 |