This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

core / spindle / mill / engine.go
2.9 kB 85 lines
1package mill 2 3import ( 4 "context" 5 "log/slog" 6 "time" 7 8 "tangled.org/core/api/tangled" 9 "tangled.org/core/spindle/engine" 10 "tangled.org/core/spindle/models" 11 "tangled.org/core/spindle/secrets" 12) 13 14// raw pipeline/workflow carried forward, executor runs the real InitWorkflow 15type millWorkflowState struct { 16 RawWorkflow tangled.Pipeline_Workflow 17 RawPipeline tangled.Pipeline 18 Lease *RemoteLease 19} 20 21// stand-in for a real engine, registered under the real names 22// ("microvm", "nixery"), all sharing one Mill 23type Engine struct { 24 name string 25 mill *Mill 26 l *slog.Logger 27} 28 29func (e *Engine) AuthorsRemoteStatus() {} 30 31func NewEngine(name string, mill *Mill) *Engine { 32 return &Engine{name: name, mill: mill, l: mill.l.With("engine", "mill:"+name)} 33} 34 35// synthetic one-step workflow so processPipeline injects TANGLED_* env 36// and marks pending normally. the real InitWorkflow runs exactly once, on 37// the executor inside ReserveSeat, and commit reuses that workflow 38func (e *Engine) InitWorkflow(twf tangled.Pipeline_Workflow, tpl tangled.Pipeline) (*models.Workflow, error) { 39 return &models.Workflow{ 40 Name: twf.Name, 41 Environment: map[string]string{}, 42 Steps: []models.Step{remoteStep{}}, 43 Data: &millWorkflowState{ 44 RawWorkflow: twf, 45 RawPipeline: tpl, 46 }, 47 }, nil 48} 49 50// no-op logger for the synthetic workflow. the executor's lines stream 51// into this wid's log directly, a local logger would just write competing 52// lines 53func (e *Engine) WorkflowLogger(wid models.WorkflowId) models.WorkflowLogger { 54 return models.NullLogger{} 55} 56 57// the placement seam, blocks on remote placement which the user sees as 58// "pending". only StartWorkflows calls this, always Wait 59func (e *Engine) AcquireWorkflowSlot(ctx context.Context, wid models.WorkflowId, wf *models.Workflow, _ engine.AcquireMode) (engine.WorkflowSlot, error) { 60 return e.mill.place(ctx, e.name, wid, wf) 61} 62 63// no-op. real setup happens on the executor 64func (e *Engine) SetupWorkflow(ctx context.Context, wid models.WorkflowId, wf *models.Workflow, wfLogger models.WorkflowLogger) error { 65 e.l.Info("remote job placed, awaiting commit", "wid", wid) 66 return nil 67} 68 69// hands over the secrets and blocks on the terminal result streamed over the 70// session 71func (e *Engine) RunStep(ctx context.Context, wid models.WorkflowId, w *models.Workflow, idx int, unlocked []secrets.UnlockedSecret, wfLogger models.WorkflowLogger) error { 72 return e.mill.commitAndWait(ctx, w, unlocked) 73} 74 75// deliberately generous, the executor enforces the real timeout. the mill 76// only caps a hung or silent executor, true death is caught by reconnect grace 77func (e *Engine) WorkflowTimeout() time.Duration { 78 return e.mill.cfg.JobTimeout 79} 80 81// cancels a still-running attempt. no-op if already terminal 82func (e *Engine) DestroyWorkflow(ctx context.Context, wid models.WorkflowId) error { 83 e.mill.destroy(wid) 84 return nil 85}