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 "errors"
6 "github.com/carlosframework/platform/internal/activator"
7 "github.com/carlosframework/platform/internal/hostbox"
8 "github.com/carlosframework/platform/internal/hostclaim"
9 "github.com/carlosframework/platform/internal/registry"
10 "time"
11)
12
13type filesSeedRuntimeFactory func(context.Context, *filesSeedOperation, *activator.SeedExclusion) (*activator.ClaimRuntime, *ClaimWakeAssembly, error)
14
15func newFilesSeedRuntime(ctx context.Context, a ClaimAssembly, source hostbox.WorkSource, writer hostbox.Writer, op *filesSeedOperation, exclusion *activator.SeedExclusion) (*activator.ClaimRuntime, *ClaimWakeAssembly, error) {
16 if a.Wake == nil || op == nil || a.wakeUnavailable != nil {
17 return nil, nil, hostbox.ErrUnsupported
18 }
19 base := a.Wake
20 var serving *claimServingOwners
21 switch in := base.Inputs.(type) {
22 case ClaimOwnerDispatch:
23 serving, _ = in.Serving.Inputs.(*claimServingOwners)
24 case *claimServingOwners:
25 serving = in
26 }
27 if serving == nil {
28 return nil, nil, hostbox.ErrUnsupported
29 }
30 sources := serving.Sources
31 sources.Files = op.files
32 private := &claimServingOwners{HomeRegion: serving.HomeRegion, Data: serving.Data, Bucket: serving.Bucket, Region: serving.Region, Box: serving.Box, NewID: serving.NewID, Now: serving.Now, Sources: sources}
33 w := &ClaimWakeAssembly{Roles: base.Roles, LeaseRegion: base.LeaseRegion, Producers: base.Producers, Inputs: private, Manager: base.Manager, Retries: base.Retries, BeforeAdmission: base.BeforeAdmission, RetireArtifacts: base.RetireArtifacts, RecoverArtifacts: base.RecoverArtifacts, RequireServingEnrollment: base.RequireServingEnrollment, BeforeLegacyInstall: base.BeforeLegacyInstall, BeforeInstallLocked: base.BeforeInstallLocked, PrepareState: base.PrepareState, Prelaunch: base.Prelaunch, Launch: base.Launch, Ready: base.Ready, ObserveLoss: base.ObserveLoss}
34 w.Retain = w.retainCaptured
35 w.ServingPrerequisites = op.prerequisites(exclusion)
36 w.AfterAdmission = func(ctx context.Context, prior, current hostclaim.Observed) error {
37 if err := base.AfterAdmission(ctx, prior, current); err != nil {
38 return err
39 }
40 return op.admitted(ctx, current)
41 }
42 w.Retries.Inputs = private.launchDigest
43 w.Retries.ExactHealth = w.exactHealth
44 w.Retries.BeforeReserve = func(ctx context.Context, rt registry.Route, o hostclaim.Observed) error {
45 if err := w.ServingPrerequisites(ctx, rt, o); err != nil {
46 return err
47 }
48 return claimServingRoom(op.files.DataDir)
49 }
50 a.Wake = w
51 a.bindClaimWakeStop()
52 writer.AdmissionEvidence = private.admissionEvidence
53 runtime, err := w.Build(ctx, source, writer)
54 return runtime, w, err
55}
56
57// The seed follows ordinary cold preparation and spends its one attempt. It
58// never calls any launch, publication, replication or health closure.
59func prepareFilesSeed(ctx context.Context, rt registry.Route, runtime *activator.ClaimRuntime, o hostclaim.Observed, exclusion *activator.SeedExclusion) (admitted hostclaim.Observed, settled bool, resultErr error) {
60 if err := exclusion.Check(rt.Host); err != nil {
61 return admitted, false, err
62 }
63 if runtime == nil || runtime.Read == nil || runtime.Prerequisites == nil || runtime.Admit == nil || runtime.Prepare == nil || runtime.FailedAdmission == nil {
64 return admitted, false, hostbox.ErrUnsupported
65 }
66 policy := activator.StartPolicy{MaxStarts: 5, Window: 30 * time.Second}
67 cleanupObservation := o
68 var start activator.ClaimStart
69 defer func() {
70 cleanup, cancel := activator.CleanupContext(ctx, 30*time.Second)
71 defer cancel()
72 var stopErr error
73 if start.Failed != nil {
74 stopErr = start.Failed(cleanup, 0)
75 }
76 closeErr := runtime.FailedAdmission(cleanup, cleanupObservation, hostbox.ErrChanged)
77 fresh, readErr := runtime.Read(cleanup, o.Host)
78 if readErr == nil {
79 if fresh.Claim == nil || fresh.Claim.Holder == nil || o.Claim == nil || o.Claim.Holder == nil || fresh.Claim.Holder.Incarnation != o.Claim.Holder.Incarnation || fresh.Claim.Holder.WakeRetry != nil && fresh.Claim.Holder.WakeRetry.State == "attempting" {
80 readErr = hostbox.ErrChanged
81 }
82 }
83 closeErr = errors.Join(closeErr, readErr)
84 settled = stopErr == nil && closeErr == nil
85 resultErr = errors.Join(resultErr, stopErr, closeErr)
86 }()
87 if err := runtime.Prerequisites(ctx, rt, o, policy); err != nil {
88 return admitted, false, err
89 }
90 var err error
91 admitted, err = runtime.Admit(ctx, rt, o, policy)
92 if err != nil {
93 return admitted, false, err
94 }
95 cleanupObservation = admitted
96 start, err = runtime.Prepare(ctx, rt, admitted, policy)
97 if err != nil {
98 return admitted, false, err
99 }
100 if start.Restore == nil || start.Reserve == nil || start.Materialize == nil || start.Failed == nil {
101 return admitted, false, hostbox.ErrUnsupported
102 }
103 if err = start.Restore(ctx); err != nil {
104 return admitted, false, err
105 }
106 if err = start.Reserve(ctx, 0); err != nil {
107 return admitted, false, err
108 }
109 if err = exclusion.Check(rt.Host); err != nil {
110 return admitted, false, err
111 }
112 resultErr = start.Materialize(ctx)
113 return admitted, false, resultErr
114}
115