Home > Backend Development > Golang > How can I perform the same workflow using cadence RegisterDelayedCallback in a unit test?

How can I perform the same workflow using cadence RegisterDelayedCallback in a unit test?

WBOY
Release: 2024-02-10 10:50:09
forward
682 people have browsed it

如何在单元测试中使用 cadence RegisterDelayedCallback 执行相同的工作流程?

php editor Baicao introduces you how to use cadence RegisterDelayedCallback in unit testing to perform the same workflow. In unit testing, we often need to simulate asynchronous operations to ensure the correctness of the code under various circumstances. cadence RegisterDelayedCallback is a powerful tool that can help us simulate delayed callback functions in tests. By using RegisterDelayedCallback, we can easily simulate asynchronous operations, ensure the correctness of the code in various situations, and be able to reproduce and fix potential problems. In this article, we will explore how to use cadence RegisterDelayedCallback to perform the same workflow to help you better unit test.

Question content

Is it possible to run unit tests using registerdelayedcallback that performs the same cadence workflow?

I have the following code that runs the workflow twice, the first execution saves the callback token and the second execution retrieves the saved token to complete the activity asynchronously.

workflow.go

package workflow

import (
    "context"
    "encoding/base64"
    "fmt"

    "go.uber.org/cadence/activity"
    "go.uber.org/cadence/workflow"
)

type workflowimpl struct {
    worker.worker
    client.client
}

func (w workflowimpl) tactivity(ctx context.context, action string) error {
    fmt.println("tactivity started", action)
    if action != "approved" {
        activityinfo := activity.getinfo(ctx)
        callbacktoken := base64.stdencoding.encodetostring(activityinfo.tasktoken)
        fmt.println("save callbacktoken", callbacktoken)
        // saves callbacktoken.

        return activity.errresultpending
    }

    fmt.println("approved")
    // do some approved things.
    // get saved callback token.
    // call w.completeactivity() with the saved callback token.
    return nil
}

func (w workflowimpl) tworkflow(ctx workflow.context, action string) (result string, err error) {
    fmt.println("tworkflow started", action)

    waitchannel := workflow.newchannel(ctx)
    workflow.go(ctx, func(ctx workflow.context) {
        if err := workflow.executeactivity(ctx, w.tactivity, action).get(ctx, nil); err != nil {
            // do nothing, keep workflow open.
            return
        }

        waitchannel.send(ctx, "ok")
    })

    var signal string
    waitchannel.receive(ctx, &signal)

    return signal, nil
}
Copy after login

workflow_test.go

package workflow_test

import (
    "time"
    "go.uber.org/cadence/worker"
)

func (s *UnitTestSuite) Test_TWorkflow() {
    env := s.NewTestWorkflowEnvironment()

    worker := workflow.WorkflowImpl{
         Worker: ...
         Client: ...
    }

    s.worker = &worker

    env.RegisterActivity(s.worker.TActivity)

    // Delay second TWorkflow.
    env.RegisterDelayedCallback(func() {
        env.ExecuteWorkflow(s.worker.TWorkflow, "Approved")
    }, time.Second*2)

    env.ExecuteWorkflow(s.worker.TWorkflow, "Noop")
    s.True(env.IsWorkflowCompleted())
    s.NoError(env.GetWorkflowError())
}
Copy after login

The above code is not complete, it does not save the callback token and call completeactivity. For the purpose of testing the sequence, I would just like to see the log of the workflow starting and the activity starting twice, but I don't see that. After the first workflow is started, if there are no active logs, the test will hang until it times out.

What's missing or is it possible to execute the same workflow twice like this?

Solution

env.registerdelayedcallback(func() {
    env.executeworkflow(s.worker.tworkflow, "approved")
}, time.second*2)
Copy after login

There is a deadlock here. env is locked while the callback is running (see source code). And the callback wants to execute the workflow on the same env, which requires acquiring the same lock on env (see source code).

Let's try to break the deadlock by running the callback in a new goroutine:

env.registerdelayedcallback(func() {
    go env.executeworkflow(s.worker.tworkflow, "approved")
}, time.second*2)
Copy after login

Now we are panicking:

panic: Current TestWorkflowEnvironment is used to execute s.worker.TWorkflow. Please create a new TestWorkflowEnvironment for s.worker.TWorkflow.
Copy after login

Currently, testworkflowenvironment cannot run 2 non-parent-child workflows. See Issues with Tracking Tasks to Enable testworkflowenvironment to support testing multiple workflows .

As the panic message suggests, you have to create a new testworkflowenvironment to execute another workflow (but I'm not sure if it's suitable for your use case).

The above is the detailed content of How can I perform the same workflow using cadence RegisterDelayedCallback in a unit test?. For more information, please follow other related articles on the PHP Chinese website!

source:stackoverflow.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template