func (tb *TaskBehavior) Done(ctx model.TaskContext) (notifyFlow bool, taskEntries []*model.TaskEntry, err error) {
	logger := ctx.FlowLogger()
	linkInsts := ctx.GetToLinkInstances()
	numLinks := len(linkInsts)
	ctx.SetStatus(model.TaskStatusDone)
	if logger.DebugEnabled() {
		logger.Debugf("Task '%s' is done", ctx.Task().ID())
	}
	if logger.DebugEnabled() {
		logger.Debugf("Task '%s' has %d outgoing links", ctx.Task().ID(), numLinks)
	}
	if numLinks > 0 {
		taskEntries = make([]*model.TaskEntry, 0, numLinks)
		var exprLinkFollowed, hasExprLink bool
		var exprOtherwiseLinkInst model.LinkInstance
		var exprOtherwiseTaskEntry *model.TaskEntry
		for _, linkInst := range linkInsts {
			linkInst.SetStatus(model.LinkStatusFalse)
			taskEntry := &model.TaskEntry{Task: linkInst.Link().ToTask(), EnterCode: 4}
			taskEntries = append(taskEntries, taskEntry)
			if linkInst.Link().Type() == definition.LtError {
				continue
			}
			if linkInst.Link().Type() == definition.LtExprOtherwise {
				exprOtherwiseLinkInst = linkInst
				exprOtherwiseTaskEntry = taskEntry
				continue
			}
			if linkInst.Link().Type() == definition.LtDependency {
				linkInst.SetStatus(model.LinkStatusTrue)
				taskEntry.EnterCode = 0
				continue
			}
			if linkInst.Link().Type() == definition.LtLabel {
				linkInst.SetStatus(model.LinkStatusTrue)
				taskEntry.EnterCode = 3
				continue
			}
			if linkInst.Link().Type() == definition.LtExpression {
				hasExprLink = true
				if logger.DebugEnabled() {
					logger.Debugf("Task '%s': Evaluating Outgoing Expression Link to Task '%s'", ctx.Task().ID(), linkInst.Link().ToTask().ID())
				}
				follow, err := ctx.EvalLink(linkInst.Link())
				if err != nil {
					if len(linkInst.Link().Label()) > 0 {
						err = fmt.Errorf("error executing link [%s -> %s] with label [%s]: %s", ctx.Task().ID(), linkInst.Link().ToTask().ID(), linkInst.Link().Label(), err.Error())
					} else {
						err = fmt.Errorf("error executing link [%s -> %s]: %s", ctx.Task().ID(), linkInst.Link().ToTask().ID(), err.Error())
					}
					return false, nil, err
				}
				if follow {
					exprLinkFollowed = true
					linkInst.SetStatus(model.LinkStatusTrue)
					taskEntry.EnterCode = 1
					if logger.DebugEnabled() {
						logger.Debugf("Task '%s': Following Expression Link to task '%s'", ctx.Task().ID(), linkInst.Link().ToTask().ID())
					}
				}
			}
		}
		if exprOtherwiseLinkInst != nil && hasExprLink && !exprLinkFollowed {
			exprOtherwiseLinkInst.SetStatus(model.LinkStatusTrue)
			exprOtherwiseTaskEntry.EnterCode = 2
			if logger.DebugEnabled() {
				logger.Debugf("Task '%s': Following Otherwise Link to task '%s'", ctx.Task().ID(), exprOtherwiseLinkInst.Link().ToTask().ID())
			}
		}
		SortTaskEntries(taskEntries)
		return false, taskEntries, nil
	}
	if logger.DebugEnabled() {
		logger.Debugf("Notifying flow that end task '%s' is done", ctx.Task().ID())
	}
	return true, nil, nil
}
Done implements model.TaskBehavior.Done
package simple
import (
	"fmt"
	"sort"
	"github.com/project-flogo/core/activity"
	"github.com/project-flogo/core/support/trace"
	"github.com/project-flogo/flow/definition"
	"github.com/project-flogo/flow/instance"
	"github.com/project-flogo/flow/model"
)
const PropagateSkip = true
type TaskBehavior struct {
}
func (tb *TaskBehavior) Enter(ctx model.TaskContext) (enterResult model.EnterResult) {
	logger := ctx.FlowLogger()
	task := ctx.Task()
	if logger.DebugEnabled() {
		logger.Debugf("Enter Task '%s'", task.ID())
	}
	ctx.SetStatus(model.TaskStatusEntered)
	linkInsts := ctx.GetFromLinkInstances()
	ready := true
	skipped := false
	if len(linkInsts) == 0 {
		ready = true
	} else {
		skipped = true
		if logger.DebugEnabled() {
			logger.Debugf("Task '%s' has %d incoming Links", task.ID(), len(linkInsts))
		}
		for _, linkInst := range linkInsts {
			if logger.DebugEnabled() {
				logger.Debugf("Task '%s': Link from Task '%s' has status '%s'", task.ID(), linkInst.Link().FromTask().ID(), linkStatus(linkInst))
			}
			if linkInst.Status() < model.LinkStatusFalse {
				ready = false
				break
			} else if linkInst.Status() == model.LinkStatusTrue {
				skipped = false
			}
		}
	}
	if ready {
		if skipped {
			ctx.SetStatus(model.TaskStatusSkipped)
			return model.ERSkip
		} else {
			if logger.DebugEnabled() {
				logger.Debugf("Task '%s' Ready", ctx.Task().ID())
			}
			ctx.SetStatus(model.TaskStatusReady)
		}
		return model.EREval
	} else {
		if logger.DebugEnabled() {
			logger.Debugf("Task '%s' Not Ready", ctx.Task().ID())
		}
	}
	return model.ERNotReady
}
func (tb *TaskBehavior) Eval(ctx model.TaskContext) (evalResult model.EvalResult, err error) {
	if ctx.Status() == model.TaskStatusSkipped {
		return model.EvalSkip, nil
	}
	task := ctx.Task()
	ctx.FlowLogger().Debugf("Eval Task '%s'", task.ID())
	done, err := evalActivity(ctx)
	if err != nil {
		ref := activity.GetRef(ctx.Task().ActivityConfig().Activity)
		ctx.FlowLogger().Errorf("Error evaluating activity '%s'[%s] - %s", ctx.Task().ID(), ref, err.Error())
		return model.EvalFail, err
	}
	if done {
		evalResult = model.EvalDone
	} else {
		evalResult = model.EvalWait
	}
	return evalResult, nil
}
func evalActivity(ctx model.TaskContext) (bool, error) {
	done, err := ctx.EvalActivity()
	if err != nil {
		if errVal, ok := err.(*activity.Error); ok && errVal.Retriable() {
			if ctx.Task().RetryOnErrConfig() == nil {
				return done, err
			}
			retryData, rerr := getRetryData(ctx)
			if rerr != nil {
				return done, rerr
			}
			if t, ok := ctx.(*instance.TaskInst); ok {
				if t.GetTracingContext() != nil {
					t.GetTracingContext().SetTag("retry_enabled", true)
					t.GetTracingContext().SetTag("retries_remaining", retryData.Count)
					t.GetTracingContext().SetTag("retry_interval_ms", retryData.Interval)
					if retryData.Count > 0 {
						_ = trace.GetTracer().FinishTrace(t.GetTracingContext(), err)
					}
				}
			}
			if retryData != nil && retryData.Count > 0 {
				return retryEval(ctx, retryData)
			}
		}
		return done, err
	}
	return done, nil
}
func (tb *TaskBehavior) PostEval(ctx model.TaskContext) (evalResult model.EvalResult, err error) {
	ctx.FlowLogger().Debugf("PostEval Task '%s'", ctx.Task().ID())
	_, err = ctx.PostEvalActivity()
	if err != nil {
		ref := activity.GetRef(ctx.Task().ActivityConfig().Activity)
		ctx.FlowLogger().Errorf("Error post evaluating activity '%s'[%s] - %s", ctx.Task().ID(), ref, err.Error())
		return model.EvalFail, err
	}
	return model.EvalDone, nil
}