cadence-client icon indicating copy to clipboard operation
cadence-client copied to clipboard

Allow registration of activities struct with a worker

Open mfateev opened this issue 7 years ago • 2 comments

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.

mfateev avatar Oct 26 '18 22:10 mfateev

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
}

Gurpartap avatar Dec 14 '19 12:12 Gurpartap

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

Gurpartap avatar Dec 14 '19 12:12 Gurpartap

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.

Groxx avatar Mar 09 '23 21:03 Groxx