我在节奏工作流中有一个疑问,我们是否可以在for循环中使用不同的输入调用同一 Activity ?该代码是否具有确定性?如果执行该工作流程的工作人员在执行过程中停止并在以后重新启动,则cadence在重新构建工作流程时将能够重播事件。
例如,我有以下代码。

   func init() {
    workflow.RegisterWithOptions(SampleWorkFlow, workflow.RegisterOptions{Name: "SampleWorkFlow"})
    activity.RegisterWithOptions(SampleActivity, activity.RegisterOptions{Name: "SampleActivity"})
    activity.RegisterWithOptions(SecondActivity, activity.RegisterOptions{Name: "SecondActivity"})
}

// SampleWorkFlow comment
func SampleWorkFlow(ctx workflow.Context, input string) error {

    fmt.Println("Workflow started")
    ctx = workflow.WithTaskList(ctx, sampleTaskList)
    ctx = workflow.WithActivityOptions(ctx, conf.ActivityOptions)

    var result string
    err := workflow.ExecuteActivity(ctx, "SampleActivity", input, "string-value").Get(ctx, &result)
    if err != nil {
        return err
    }

    for i := 1; i <= 10; i++ {
        value := i
        workflow.Go(ctx, func(ctx workflow.Context) {
            err := workflow.ExecuteActivity(ctx, "SecondActivity", input, value).Get(ctx, &result)
            if err != nil {
                log.Println("err=", err)
            }
        })
    }

    return nil

}

// SampleActivity comment
func SampleActivity(ctx context.Context, value, v1 string) (string, error) {
    fmt.Println("Sample activity start")
    for i := 0; i <= 10; i++ {
        fmt.Println(i)
    }
    return "Hello " + value, nil
}

// SecondActivity comment
func SecondActivity(ctx context.Context, value int) (string, error) {

    fmt.Println("Second  activity start")

    fmt.Println("value=", value)
    fmt.Println("Second activity going to end")
    return "Hello " + fmt.Sprintf("%d", value), nil
}
在这里,第二个 Activity 在for循环内并行调用。
我的第一个问题是这段代码是确定性的吗?
假设在循环的5次迭代之后,当i = 5时,执行此工作流程的工作人员将终止,如果工作流程在另一个流程中启动,则节奏可以重播事件
worker ?
你能回答我的问题吗?

最佳答案

是的,此代码是确定性的。它不会调用任何非确定性操作(如随机或UUID生成),而是使用workflow.Go启动goroutine。因此它是确定性的。代码的复杂性在定义其确定性方面不起作用。
无关的尼特。无需在示例中使用goroutine,因为ExecuteActivity调用已经通过返回Future进行了非阻塞。
因此,样本可以简化为:

func SampleWorkFlow(ctx workflow.Context, input string) error {

    fmt.Println("Workflow started")
    ctx = workflow.WithTaskList(ctx, sampleTaskList)
    ctx = workflow.WithActivityOptions(ctx, conf.ActivityOptions)

    var result string
    err := workflow.ExecuteActivity(ctx, "SampleActivity", input, "string-value").Get(ctx, &result)
    if err != nil {
        return err
    }

    for i := 1; i <= 10; i++ {
       workflow.ExecuteActivity(ctx, "SecondActivity", input, i)
    }
    return nil
}
请注意,此示例仍然可以按预期方式执行,因为它无需等待 Activity 完成即可完成工作流。因此,这些 Activity 甚至都不会开始。
这是等待 Activity 完成的代码:
func SampleWorkFlow(ctx workflow.Context, input string) error {

    fmt.Println("Workflow started")
    ctx = workflow.WithTaskList(ctx, sampleTaskList)
    ctx = workflow.WithActivityOptions(ctx, conf.ActivityOptions)

    var result string
    err := workflow.ExecuteActivity(ctx, "SampleActivity", input, "string-value").Get(ctx, &result)
    if err != nil {
        return err
    }
    var results []workflow.Future
    for i := 1; i <= 10; i++ {
        future := workflow.ExecuteActivity(ctx, "SecondActivity", input, i)
        results = append(results, future)
    }
    for i := 0; i < 10; i++ {
        var result string
        err := results[i].Get(ctx, &result)
        if err != nil {
            log.Println("err=", err)
        }
    }
    return nil
}

关于go - 在节奏工作流中的循环内调用相同的事件,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/64068770/

10-12 05:11