uber-go / cadence-client

Framework for authoring workflows and activities running on top of the Cadence orchestration engine.

Home Page:https://cadenceworkflow.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Cadence Go client improvement ideas

mfateev opened this issue · comments

Cadence Go client has been used in production for over two years. While it has been pretty well received there are known issues which we would like to fix in the next major (possibly incompatible release).

The known issues to address:

  • Allow registration of activities struct with a worker (#600)
  • Get rid of static register calls
  • Add a code generator to allow calling activities by the interface they implement as it is done in Java client.
  • Add middleware to allow intercepting workflow API calls like (ExecuteActivity)
  • Consider not using context for passing ActivityOptions and ChildWorkflowOptions
  • Channel.Receive should return error as this calls involves deserialization when channel is a signal one
  • Add Channel.ReceiveWithTimeout
  • Selector API can be simplified. For example selector.AddTimeout(duration) can be added.

Feel free to add your ideas about possible improvements.

I would consider using OpenCensus or OpenTelemetry instead of Tally. Uber is already a part of the OpenTelemetry effort through Jaeger. (Not sure if this is actually a client issue, but I can see tally in the list of dependencies)

I've got a couple of ideas:

  • New error values. I wonder if cadence-client would benefit from the new error values added to the standard library? E.g., would it deprecate functions like IsGenericError? Available since Go 1.13 but also in older versions via golang.org/x/xerrors. Interesting reads: [1], [2].
  • Aliased types. I found hard to get used to aliased types. I'm sure there must be a good reason to export types that way, but it's not very clear for new users how to follow them. E.g. when I land to https://godoc.org/go.uber.org/cadence I see the RetryPolicy type with a one-line comment. I need to click on internal.RetryPolicy which is clarifying but it also brings the user to a package of unexported types. Perhaps a good start could be to clarify the use of the internal package, perhaps with a mention in cadence.go and/or https://cadenceworkflow.io/docs/07_goclient/.

I would like to see something to better manage waiting for activities that does not return any value. Adding a Future.Wait method seems like the most straightforward solution to me.

I would like to see something to better manage waiting for activities that does not return any value. Adding a Future.Wait method seems like the most straightforward solution to me.

@furuholm, I've been using Future.Get(ctx, nil). Have you tried that? But I think that your method would be nicer.

@sevein I have, and I could have sworn that I got an error when I did that. I will try again. Thanks for the advice!

From a convo in Slack, the user requests to make available general helpers for creating clients and worker services. I understand that most of the complexity origins in creating the workflowserviceclient object because it requires a yarpc dispatcher plus tchannel transport. I guess that it could be similar to the build helper in factory.go that is part of cadence-samples.

@sevein I tried Future.Get(ctx, nil) and it worked. I must have tried Future.Get(ctx) when I didn't get it to work.

Consider merging Client.StartWorkflow and ExecuteWorkflow as ExecuteWorkflow returns a future that might be used to get runID and workflowID and waiting for completion through Get is optional.

  • Allow registration of activities struct with a worker (#600)

Registering SampleStruct{Dep: dep}.PerformFunc as a workflow or an activity, and referencing SampleStruct{}.PerformFunc for execution already works.

It's, apparently, also not necessary to use string names in calls to ExecuteWorkflow/ExecuteActivity. I'll share an example in #600.

That only works if the worker and the publisher share the same codebase.

That only works if the worker and the publisher share the same codebase.

Wouldn't it be the same case for a standalone func as well?

Disparate codebases would necessitate stringly typed workflow/activity names.

Yeah, it would. I kinda mixed up two things together here.

So registering structs is not possible at the moment. Registering a struct would mean that all of it's exported functions are registered as workflows/activities.

What I referred to is indeed a different problem, but AFAIK the new struct registration implementation will also include simpler naming conventions.