~ knotless Search/
↑↓ move↵ open⇧↵ all results
0
0
main
76 lines · 2.1 KB Raw History
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
}