feat: expose bounded workflow activation and signal history
This commit is contained in:
@@ -8,6 +8,7 @@ import (
|
||||
"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"
|
||||
)
|
||||
@@ -37,43 +38,51 @@ func (s *WorkflowInstanceStore) Step(ctx context.Context, t auth.Token, id core.
|
||||
return err
|
||||
}
|
||||
out.Input, out.Output = input, output
|
||||
program, err := engine.Compile(version.Specification)
|
||||
if err != nil {
|
||||
return 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, t.NamespaceID, id, a).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 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 errors.New("workflow poll detail ownership or policy invalid")
|
||||
}
|
||||
out.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=?`, t.NamespaceID, id, a).Scan(&w.ID, &w.Kind, &w.State, &w.Name, &w.PayloadVersion, &w.CorrelationKey, &w.DeadlineAt, &w.WinnerSignalID, &w.ResolvedAt); err != nil {
|
||||
return err
|
||||
}
|
||||
if w.Kind != string(out.Step.Kind) {
|
||||
return 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'`, t.NamespaceID, id, w.WinnerSignalID, w.ID, key, out.Step.ActivationSequence).Scan(&n); err != nil {
|
||||
return err
|
||||
}
|
||||
if n != 1 {
|
||||
return errors.New("workflow wait winner association invalid")
|
||||
}
|
||||
}
|
||||
out.Wait = w
|
||||
}
|
||||
return nil
|
||||
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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user