89 lines
4.5 KiB
Go
89 lines
4.5 KiB
Go
package mysql
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"errors"
|
|
|
|
"git.yuntuo.hk/k2safe/orbit/internal/fault"
|
|
core "git.yuntuo.hk/k2safe/orbit/model"
|
|
"git.yuntuo.hk/k2safe/orbit/platform/auth"
|
|
"git.yuntuo.hk/k2safe/orbit/weave/definition"
|
|
"git.yuntuo.hk/k2safe/orbit/weave/engine"
|
|
"git.yuntuo.hk/k2safe/orbit/weave/instance"
|
|
)
|
|
|
|
func (s *WorkflowInstanceStore) Step(ctx context.Context, t auth.Token, id core.ID, key string) (instance.StepDetail, error) {
|
|
out := instance.StepDetail{InstanceID: id}
|
|
err := s.transaction(ctx, t, instance.ReadAction, func(tx *sql.Tx, p auth.Permissions) error {
|
|
v, gate, version, err := readWorkflowForQuery(ctx, tx, t.NamespaceID, id, p)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
out.Revision = v.Revision
|
|
steps, err := readWorkflowStepViews(ctx, tx, t.NamespaceID, id, gate, version, key)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if len(steps) != 1 {
|
|
return fault.NotFound
|
|
}
|
|
out.Step = steps[0]
|
|
a := out.Step.ActivationID
|
|
if a == nil {
|
|
return nil
|
|
}
|
|
var input, output []byte
|
|
if err = tx.QueryRowContext(ctx, `SELECT input,output,created_at,completed_at FROM weave_activations WHERE namespace_id=? AND workflow_id=? AND step_id=? AND id=?`, t.NamespaceID, id, out.Step.ID, a).Scan(&input, &output, &out.ActivatedAt, &out.CompletedAt); err != nil {
|
|
return err
|
|
}
|
|
out.Input, out.Output = input, output
|
|
out.Poll, out.Wait, err = readWorkflowActivationAttachments(ctx, tx, t.NamespaceID, id, gate, key, string(out.Step.Kind), *a, out.Step.ActivationSequence, version)
|
|
return err
|
|
})
|
|
return out, err
|
|
}
|
|
|
|
// readWorkflowActivationAttachments 查询指定激活的等待与预算,不替换为当前激活。
|
|
func readWorkflowActivationAttachments(ctx context.Context, tx *sql.Tx, ns, workflow, gate core.ID, key, kind string, activation core.ID, sequence uint32, version definition.VersionView) (*instance.PollView, *instance.WaitView, error) {
|
|
var poll *instance.PollView
|
|
var wait *instance.WaitView
|
|
program, err := engine.Compile(version.Specification)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
node, _ := program.Step(key)
|
|
if node.Poll != nil {
|
|
q := &instance.PollView{}
|
|
var owned, queue *core.ID
|
|
err = tx.QueryRowContext(ctx, "SELECT p.used_rounds,p.first_round,p.first_round_attempts_used,p.max_rounds,p.max_attempts_per_round,p.interval_ms,p.deadline_at,p.next_poll_at,p.current_task_id,r.task_id,p.resolved_at,t.id,t.queue_id FROM weave_poll_states p JOIN weave_poll_rounds r ON r.namespace_id=p.namespace_id AND r.workflow_id=p.workflow_id AND r.activation_id=p.activation_id AND r.`round`=p.used_rounds LEFT JOIN pulse_tasks t ON t.namespace_id=r.namespace_id AND t.id=r.task_id AND t.owner_kind='workflow_activation' AND t.owner_id=r.activation_id AND t.gate_id=? WHERE p.namespace_id=? AND p.workflow_id=? AND p.activation_id=?", gate, ns, workflow, activation).Scan(&q.UsedRounds, &q.FirstRound, &q.FirstRoundAttemptsUsed, &q.MaxRounds, &q.MaxAttemptsPerRound, &q.IntervalMS, &q.DeadlineAt, &q.NextPollAt, &q.CurrentTaskID, &q.LastTaskID, &q.ResolvedAt, &owned, &queue)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
if owned == nil || *owned != q.LastTaskID || queue == nil || *queue != node.Poll.Task.QueueID || q.CurrentTaskID != nil && *q.CurrentTaskID != q.LastTaskID || q.MaxRounds != node.Poll.MaxRounds || q.MaxAttemptsPerRound != node.Poll.Task.Retry.MaxAttempts || q.IntervalMS != node.Poll.IntervalMS {
|
|
return nil, nil, errors.New("workflow poll detail ownership or policy invalid")
|
|
}
|
|
poll = q
|
|
}
|
|
if node.Signal != nil || node.Timer != nil || node.Poll != nil && node.Poll.FinalSignal != nil {
|
|
w := &instance.WaitView{}
|
|
if err = tx.QueryRowContext(ctx, `SELECT id,kind,state,signal_name,payload_version,correlation_key,deadline_at,winner_signal_id,resolved_at FROM weave_waits WHERE namespace_id=? AND workflow_id=? AND activation_id=?`, ns, workflow, activation).Scan(&w.ID, &w.Kind, &w.State, &w.Name, &w.PayloadVersion, &w.CorrelationKey, &w.DeadlineAt, &w.WinnerSignalID, &w.ResolvedAt); err != nil {
|
|
return nil, nil, err
|
|
}
|
|
if w.Kind != kind {
|
|
return nil, nil, errors.New("workflow wait kind mismatch")
|
|
}
|
|
if w.WinnerSignalID != nil {
|
|
var n int
|
|
if err = tx.QueryRowContext(ctx, `SELECT COUNT(*) FROM weave_signals WHERE namespace_id=? AND workflow_id=? AND id=? AND consumed_wait_id=? AND target_step_key=? AND target_activation_sequence=? AND state='CONSUMED'`, ns, workflow, w.WinnerSignalID, w.ID, key, sequence).Scan(&n); err != nil {
|
|
return nil, nil, err
|
|
}
|
|
if n != 1 {
|
|
return nil, nil, errors.New("workflow wait winner association invalid")
|
|
}
|
|
}
|
|
wait = w
|
|
}
|
|
return poll, wait, nil
|
|
}
|