cadence-client
cadence-client copied to clipboard
Allow registration of activities struct with a worker
Users prefer initializing a struct that implements activities with all external dependencies. It also works well with DI frameworks. The downside is that all calls to ExecuteActivity have to use string names of the activities.
The downside is that all calls to ExecuteActivity have to use string names of the activities.
Continuing from https://github.com/uber-go/cadence-client/issues/849#issuecomment-565713200
While RegisterOption{Name string} takes care of correct representation in the UI, it is not necessary to refer to the same string name when executing a workflow or activity.
Referencing SampleStruct{}.PerformFunc for execution works just as good. This means runtime param validation works too!
I do something like this:
package main
func main() {
apiKey := "key"
apiSecret := "secret"
db, _ := openDB()
workflows.RegisterSampleWorkflow(apiKey, apiSecret)
activities.RegisterSampleActivity(db)
_, err := workflowClient.StartWorkflow(ctx, opts,
workflows.SampleWorkflow{}.Perform, // ☑️
"value",
)
}
package workflows
func RegisterSampleWorkflow(apiKey, apiSecret string) {
workflow.RegisterWithOptions(
SampleWorkflow{APIKey: apiKey, APISecret: apiSecret}.Perform, // ☑️
workflow.RegisterOptions{Name: reflect.TypeOf(SampleWorkflow{}).Name()},
// or: workflow.RegisterOptions{Name: "SampleWorkflow"},
)
}
type SampleWorkflow struct {
apiKey string
apiSecret string
}
func (wf SampleWorkflow) Perform(ctx workflow.Context, value string) error {
future := workflow.ExecuteActivity(
opts,
activities.SampleActivity{}.Perform, // ☑️
wf.apiKey, wf.apiSecret,
)
// …
}
package activities
func RegisterSampleActivity(db *sqlx.DB) {
activity.RegisterWithOptions(
SampleActivity{DB: db}.Perform, // ☑️
activity.RegisterOptions{Name: reflect.TypeOf(SampleActivity{}).Name()},
// or: activity.RegisterOptions{Name: "SampleActivity"},
)
}
type SampleActivity struct {
DB *sqlx.DB
}
func (activity SampleActivity) Perform(ctx workflow.Context, apiKey, apiSecret string) error {
// use activity.DB
}
Perhaps, thanks to this getFunctionName(), which works just as good with Struct{}.Func as it does with an adhoc Func.
https://github.com/uber-go/cadence-client/blob/a67d04578899bcddb579f43b08d21ab32b0400ff/internal/internal_worker.go#L1287-L1289
As @Gurpartap points out, this has always been possible, and quite simply. Or people can write a downright trivial loop over instance methods -> call activity.Register to do it implicitly if they want. Better to not obfuscate things.