Add semantic configuration resume evidence
This commit is contained in:
95
internal/app/semantic_resume.go
Normal file
95
internal/app/semantic_resume.go
Normal file
@@ -0,0 +1,95 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"gitea.maximumdirect.net/eric/narratio/internal/manifest"
|
||||
"gitea.maximumdirect.net/eric/narratio/internal/stage"
|
||||
)
|
||||
|
||||
func currentStageSemanticConfig(selected stage.Stage, env *stage.Env) (*manifest.SemanticConfigFingerprint, error) {
|
||||
provider, ok := selected.(stage.SemanticConfigFingerprinter)
|
||||
if !ok {
|
||||
return nil, nil
|
||||
}
|
||||
record, err := provider.SemanticConfigFingerprint(env)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := record.Validate(); err != nil {
|
||||
return nil, fmt.Errorf("invalid current semantic configuration fingerprint: %w", err)
|
||||
}
|
||||
return cloneSemanticConfig(&record), nil
|
||||
}
|
||||
|
||||
func validateStageSemanticResume(selected stage.Stage, m *manifest.Manifest, current *manifest.SemanticConfigFingerprint) stage.ResumeValidation {
|
||||
if current == nil {
|
||||
return stage.Resumable()
|
||||
}
|
||||
var persisted *manifest.SemanticConfigFingerprint
|
||||
if m != nil && m.Stages != nil && m.Stages[selected.Name()] != nil {
|
||||
persisted = m.Stages[selected.Name()].SemanticConfig
|
||||
}
|
||||
if persisted == nil {
|
||||
return stage.NonResumable("semantic configuration evidence is missing; rerun the stage to establish current evidence")
|
||||
}
|
||||
if err := persisted.Validate(); err != nil {
|
||||
return stage.NonResumable("persisted semantic configuration evidence is malformed; rerun the stage")
|
||||
}
|
||||
if persisted.Version != current.Version {
|
||||
return stage.NonResumable("semantic configuration contract version changed; rerun the stage")
|
||||
}
|
||||
if persisted.Digest != current.Digest {
|
||||
return stage.NonResumable("result-affecting configuration changed; rerun the stage")
|
||||
}
|
||||
return stage.Resumable()
|
||||
}
|
||||
|
||||
func evaluateStageResume(
|
||||
ctx context.Context,
|
||||
selected stage.Stage,
|
||||
env *stage.Env,
|
||||
m *manifest.Manifest,
|
||||
current *manifest.SemanticConfigFingerprint,
|
||||
) (*stage.ResumeValidation, error) {
|
||||
semantic := validateStageSemanticResume(selected, m, current).Normalized()
|
||||
if !semantic.Resumable {
|
||||
return &semantic, nil
|
||||
}
|
||||
validator, ok := selected.(stage.ResumeValidator)
|
||||
if !ok {
|
||||
if current == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return &semantic, nil
|
||||
}
|
||||
validation, err := validator.ValidateResume(ctx, env, m)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
validation = validation.Normalized()
|
||||
return &validation, nil
|
||||
}
|
||||
|
||||
func setSessionStageSemanticConfig(m *manifest.Manifest, name string, value *manifest.SemanticConfigFingerprint) {
|
||||
if m == nil || m.Stages == nil || m.Stages[name] == nil {
|
||||
return
|
||||
}
|
||||
m.Stages[name].SemanticConfig = cloneSemanticConfig(value)
|
||||
}
|
||||
|
||||
func setRunStageSemanticConfig(m *manifest.RunManifest, name string, value *manifest.SemanticConfigFingerprint) {
|
||||
if m == nil || m.Stages == nil || m.Stages[name] == nil {
|
||||
return
|
||||
}
|
||||
m.Stages[name].SemanticConfig = cloneSemanticConfig(value)
|
||||
}
|
||||
|
||||
func cloneSemanticConfig(value *manifest.SemanticConfigFingerprint) *manifest.SemanticConfigFingerprint {
|
||||
if value == nil {
|
||||
return nil
|
||||
}
|
||||
copy := *value
|
||||
return ©
|
||||
}
|
||||
Reference in New Issue
Block a user