carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

1package host
2
3import (
4 "context"
5 "crypto/rand"
6 "encoding/hex"
7 "errors"
8 "sync"
9
10 "github.com/carlosframework/platform/internal/hostbox"
11 execlease "github.com/carlosframework/platform/internal/hostexec"
12 "github.com/carlosframework/platform/internal/hostguard"
13 "github.com/carlosframework/platform/internal/rootparticipation"
14 "github.com/carlosframework/platform/internal/rootstate"
15)
16
17var openClaimExecutionAuthority = func() (rootstate.Store, error) {
18 return rootstate.Open(rootparticipation.Namespace, true, false)
19}
20
21type claimExecutionRuntime struct {
22 parks *servingParkRuntime
23 broker *execlease.RootBroker
24 state rootstate.Store
25 mu sync.Mutex
26 cancel context.CancelFunc
27 done chan struct{}
28 closed bool
29 root *ClaimRootHTTP
30}
31
32func newClaimExecutionRuntime(h ClaimRootHTTP, state rootstate.Store) (*claimExecutionRuntime, error) {
33 boot, err := execlease.BootID()
34 if err != nil {
35 return nil, err
36 }
37 var id [32]byte
38 if _, err = rand.Read(id[:]); err != nil {
39 return nil, err
40 }
41 ledger := rootparticipation.Ledger{State: state, VerifyLaunches: rootparticipation.VerifyLaunchCensus}
42 runtime := &claimExecutionRuntime{state: state, root: &h}
43 broker, err := execlease.NewRootBroker(execlease.RootBrokerConfig{
44 State: state, Remote: h.Stop.Coordinator.Evidence, Clock: execlease.SystemClock{}, BootID: boot, Identity: hex.EncodeToString(id[:]),
45 Authority: func(ctx context.Context, q execlease.ExecutionRequest, peer execlease.ControllerProcess) (execlease.ExecutionAuthority, error) {
46 a, err := runtime.root.executionAuthorityWithMigration(ctx, state, q, peer)
47 if errors.Is(err, hostbox.ErrChanged) || errors.Is(err, hostbox.ErrTypedInventory) || errors.Is(err, hostguard.ErrFenced) || errors.Is(err, hostguard.ErrStampMismatch) || errors.Is(err, hostguard.ErrRetiredStamp) {
48 err = errors.Join(execlease.ErrInactive, err)
49 }
50 return a, err
51 },
52 Alive: execlease.ControllerAlive,
53 Cleanup: func(ctx context.Context, r execlease.ExecutionRecord) error {
54 return runtime.root.cleanupExecution(ctx, r)
55 },
56 Settle: func(ctx context.Context, r execlease.ExecutionRecord) error {
57 return runtime.root.settleExecution(ctx, r)
58 },
59 Transition: func(ctx context.Context, r execlease.ExecutionRecord, q execlease.ExecutionRequest, a execlease.ExecutionAuthority) error {
60 return runtime.root.transitionExecution(ctx, r, q, a)
61 },
62 Exclude: ledger.Acquire,
63 Recovered: func(ctx context.Context) error {
64 return rootparticipation.WithLaunchExclusion(ctx, ledger.RecoverAcquisition)
65 },
66 })
67 if err != nil {
68 return nil, err
69 }
70 runtime.broker = broker
71 return runtime, nil
72}
73
74func (r *claimExecutionRuntime) Start(ctx context.Context) {
75 r.mu.Lock()
76 defer r.mu.Unlock()
77 if r.closed || r.done != nil {
78 return
79 }
80 worker, cancel := context.WithCancel(ctx)
81 r.cancel, r.done = cancel, make(chan struct{})
82 go func() { defer close(r.done); r.broker.Run(worker) }()
83}
84
85func (r *claimExecutionRuntime) Close(ctx context.Context) error {
86 r.mu.Lock()
87 defer r.mu.Unlock()
88 if r.closed {
89 return nil
90 }
91 if r.cancel != nil {
92 r.cancel()
93 select {
94 case <-r.done:
95 case <-ctx.Done():
96 return ctx.Err()
97 }
98 }
99 if err := r.parks.Close(ctx); err != nil {
100 return err
101 }
102 err := r.broker.Close(ctx)
103 if ctx.Err() != nil {
104 return errors.Join(err, ctx.Err())
105 }
106 r.closed = true
107 return errors.Join(err, r.state.Close())
108}
109