processNodeRetries updates the retry node state based on the child node state and the retry strategy and returns the node.
(ctx context.Context, node *wfv1.NodeStatus, retryStrategy wfv1.RetryStrategy, opts *executeTemplateOpts)
| 978 | |
| 979 | // processNodeRetries updates the retry node state based on the child node state and the retry strategy and returns the node. |
| 980 | func (woc *wfOperationCtx) processNodeRetries(ctx context.Context, node *wfv1.NodeStatus, retryStrategy wfv1.RetryStrategy, opts *executeTemplateOpts) (*wfv1.NodeStatus, bool, error) { |
| 981 | if node.Phase.Fulfilled(node.TaskResultSynced) { |
| 982 | return node, true, nil |
| 983 | } |
| 984 | |
| 985 | childNodeIds, lastChildNode := getChildNodeIdsAndLastRetriedNode(node, woc.wf.Status.Nodes) |
| 986 | if len(childNodeIds) == 0 { |
| 987 | return node, true, nil |
| 988 | } |
| 989 | |
| 990 | if lastChildNode == nil { |
| 991 | return node, true, nil |
| 992 | } |
| 993 | |
| 994 | if lastChildNode.IsDaemoned() { |
| 995 | node.Daemoned = ptr.To(true) |
| 996 | } |
| 997 | |
| 998 | if !lastChildNode.Phase.Fulfilled(lastChildNode.TaskResultSynced) { |
| 999 | if !lastChildNode.IsDaemoned() { |
| 1000 | return node, true, nil |
| 1001 | } |
| 1002 | // last child node is still running. |
| 1003 | node = woc.markNodePhase(ctx, node.Name, lastChildNode.Phase) |
| 1004 | if lastChildNode.IsDaemoned() { // markNodePhase doesn't pass the Daemoned field |
| 1005 | node.Daemoned = ptr.To(true) |
| 1006 | } |
| 1007 | return node, true, nil |
| 1008 | } |
| 1009 | |
| 1010 | if !lastChildNode.FailedOrError() { |
| 1011 | node.Outputs = lastChildNode.Outputs.DeepCopy() |
| 1012 | woc.wf.Status.Nodes.Set(ctx, node.ID, *node) |
| 1013 | return woc.markNodePhase(ctx, node.Name, wfv1.NodeSucceeded), true, nil |
| 1014 | } |
| 1015 | |
| 1016 | if woc.GetShutdownStrategy().Enabled() || (woc.workflowDeadline != nil && time.Now().UTC().After(*woc.workflowDeadline)) { |
| 1017 | var message string |
| 1018 | if woc.GetShutdownStrategy().Enabled() { |
| 1019 | message = fmt.Sprintf("Stopped with strategy '%s'", woc.GetShutdownStrategy()) |
| 1020 | } else { |
| 1021 | message = fmt.Sprintf("retry exceeded workflow deadline %s", *woc.workflowDeadline) |
| 1022 | } |
| 1023 | woc.log.Info(ctx, message) |
| 1024 | return woc.markNodePhase(ctx, node.Name, lastChildNode.Phase, message), true, nil |
| 1025 | } |
| 1026 | |
| 1027 | if retryStrategy.Backoff != nil { |
| 1028 | maxDurationDeadline := time.Time{} |
| 1029 | // Process max duration limit |
| 1030 | if retryStrategy.Backoff.MaxDuration != "" && len(childNodeIds) > 0 { |
| 1031 | maxDuration, err := wfv1.ParseStringToDuration(retryStrategy.Backoff.MaxDuration) |
| 1032 | if err != nil { |
| 1033 | return nil, false, err |
| 1034 | } |
| 1035 | firstChildNode, err := woc.wf.Status.Nodes.Get(childNodeIds[0]) |
| 1036 | if err != nil { |
| 1037 | return nil, false, err |