| 1 | package boot |
| 2 | |
| 3 | import ( |
| 4 | "fmt" |
| 5 | "reasonix/internal/agent" |
| 6 | "reasonix/internal/config" |
| 7 | "reasonix/internal/control" |
| 8 | "reasonix/internal/event" |
| 9 | "reasonix/internal/jobs" |
| 10 | "reasonix/internal/workspacelease" |
| 11 | "time" |
| 12 | ) |
| 13 | |
| 14 | func acquireBackgroundScope(scope *jobs.SessionBackgroundScope, root string, sink event.Sink, stalledSeconds int) (*jobs.SessionBackgroundScope, error) { |
| 15 | if scope != nil { |
| 16 | if err := scope.Acquire(); err != nil { |
| 17 | return nil, err |
| 18 | } |
| 19 | return scope, nil |
| 20 | } |
| 21 | lease, err := workspacelease.New(root, config.WorkspaceLeaseDir(), func() { |
| 22 | notice := event.Event{Kind: event.Notice, Level: event.LevelInfo, Code: event.NoticeCodeWorkspaceLease, |
| 23 | Text: "Another session is writing to this workspace; this session will continue automatically when it is safe.", |
| 24 | Detail: "workspace write lease is busy; read-only work remains concurrent"} |
| 25 | if scope != nil { |
| 26 | scope.Manager.Emit(notice) |
| 27 | } else { |
| 28 | sink.Emit(notice) |
| 29 | } |
| 30 | }) |
| 31 | if err != nil { |
| 32 | return nil, fmt.Errorf("initialize workspace write lease: %w", err) |
| 33 | } |
| 34 | scope = jobs.NewSessionBackgroundScope(jobs.NewManager(sink, |
| 35 | jobs.WithStalledWarningAfter(time.Duration(stalledSeconds)*time.Second), |
| 36 | jobs.WithSessionOwnershipProbe(agent.SessionLeaseHeldByCurrentRuntime), |
| 37 | jobs.WithJobStartObserver(lease.RetainUntil)), lease) |
| 38 | return scope, nil |
| 39 | } |
| 40 | |
| 41 | func releaseBackgroundBuild(scope *jobs.SessionBackgroundScope, controller *control.Controller) { |
| 42 | if controller != nil { |
| 43 | controller.ReleaseResources() |
| 44 | } else { |
| 45 | scope.Release(false) |
| 46 | } |
| 47 | } |
| 48 | |
| 49 | func stageModelRuntimePublication(res *BuildResult, opts Options) { |
| 50 | _ = res.Owner.Gate.SweepAndForceExpire() |
| 51 | res.Controller.StageReplacementPublication(func() { |
| 52 | publishPreparedBuildResult(res) |
| 53 | if opts.Extensions != nil && res.Plan != nil { |
| 54 | go opts.Extensions.DrainPlan(res.Plan) |
| 55 | } |
| 56 | }) |
| 57 | } |
| 58 |