1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
package controller
import (
"context"
"encoding/json"
"errors"
"fmt"
"github.com/johnandersen777/socialweb-computer-kcp/internal/contract/policy"
policyengine "github.com/johnandersen777/socialweb-computer-kcp/internal/policyengine/status"
)
type Tasks struct {
Engine *Engine
}
var _ policy.Engine = Tasks{}
func (t Tasks) Submit(ctx context.Context, workflow []byte, inputs map[string]string) (string, error) {
if t.Engine == nil {
return "", errors.New("policy engine: no in-process engine is running")
}
if !json.Valid(workflow) {
return "", errors.New("policy engine: the workflow is not valid JSON")
}
values := make(map[string]any, len(inputs))
for key, value := range inputs {
values[key] = value
}
return t.Engine.Submit(ctx, &PolicyEngineRequest{Workflow: append([]byte(nil), workflow...), Inputs: values}, RunOptions{})
}
func (t Tasks) Status(_ context.Context, taskID string) (policy.Task, error) {
if t.Engine == nil {
return policy.Task{}, errors.New("policy engine: no in-process engine is running")
}
status, ok := t.Engine.RunStatus(taskID)
if !ok {
return policy.Task{}, fmt.Errorf("policy engine: task %s not found", taskID)
}
if !status.Phase.Terminal() {
return policy.Task{State: policy.StateRunning}, nil
}
task := policy.Task{ExitStatus: string(status.ExitStatus), Outputs: stringify(status.Outputs)}
if status.Phase == policyengine.PhaseSucceeded {
task.State = policy.StateSucceeded
return task, nil
}
task.State = policy.StateFailed
if task.ExitStatus != "" {
task.Message = "the workflow exited with status " + task.ExitStatus
} else {
task.Message = "the policy engine did not report a success exit status"
}
return task, nil
}
func stringify(values map[string]any) map[string]string {
if len(values) == 0 {
return nil
}
out := make(map[string]string, len(values))
for key, value := range values {
if text, ok := value.(string); ok {
out[key] = text
continue
}
encoded, err := json.Marshal(value)
if err != nil {
out[key] = fmt.Sprint(value)
continue
}
out[key] = string(encoded)
}
return out
}