-
Notifications
You must be signed in to change notification settings - Fork 186
Support named workflows and activities #744
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 5 commits
9b85096
40fed9b
d341805
3bc00c8
5fb3c61
0d7e561
d5858cc
b82732f
d97e285
4a7c58c
37deb0d
7c081b5
3becd4b
41c8e26
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -20,6 +20,7 @@ import ( | |
| "fmt" | ||
| "log" | ||
| "reflect" | ||
| "regexp" | ||
| "runtime" | ||
| "strings" | ||
|
|
||
|
|
@@ -90,10 +91,15 @@ func getFunctionName(f interface{}) (string, error) { | |
| } | ||
|
|
||
| callSplit := strings.Split(runtime.FuncForPC(reflect.ValueOf(f).Pointer()).Name(), ".") | ||
|
|
||
| funcName := callSplit[len(callSplit)-1] | ||
|
|
||
| if funcName == "1" { | ||
| const anonymousFunctionRegexp = "^func[0-9]+$" | ||
| isAnonymousFunc, err := regexp.MatchString(anonymousFunctionRegexp, funcName) | ||
| if err != nil { | ||
| return "", fmt.Errorf("failed to match anonymous function regexp: %w", err) | ||
| } | ||
|
|
||
| if isAnonymousFunc { | ||
| return "", errors.New("anonymous function name") | ||
| } | ||
|
|
||
|
|
@@ -107,18 +113,43 @@ func wrapWorkflow(w Workflow) task.Orchestrator { | |
| } | ||
| } | ||
|
|
||
| type registerOptions struct { | ||
| Name string | ||
| } | ||
|
|
||
| type registerOption func(*registerOptions) error | ||
|
|
||
| // RegisterWithName allows you to specify a custom name for the workflow or activity being registered. | ||
| // Activities and Workflows registered without an explicit name will use the function name as the name. | ||
| func RegisterWithName(name string) registerOption { | ||
| return func(opts *registerOptions) error { | ||
| opts.Name = name | ||
| return nil | ||
| } | ||
| } | ||
|
|
||
| // RegisterWorkflow adds a workflow function to the registry | ||
| func (ww *WorkflowWorker) RegisterWorkflow(w Workflow) error { | ||
| func (ww *WorkflowWorker) RegisterWorkflow(w Workflow, opts ...registerOption) error { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This breaks the func API- please can we create new funcs which take an options.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Which API do you think this break?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is somewhat compatible however there are some cases if you're implementing it within an interface or using reflection it would be a breaking change as the function signature is distinctly different I think in the interests of time I would be inclined to agree that a new method with the variadic parameters for the time being would be the best path forwards while a deprecation/upgrade path is defined. Wdyt?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't mind adding another function for this, |
||
| wrappedOrchestration := wrapWorkflow(w) | ||
|
|
||
| // get the function name for the passed workflow | ||
| name, err := getFunctionName(w) | ||
| if err != nil { | ||
| return fmt.Errorf("failed to get workflow decorator: %v", err) | ||
| options := registerOptions{} | ||
| for _, opt := range opts { | ||
| if err := opt(&options); err != nil { | ||
| return fmt.Errorf("failed processing options: %w", err) | ||
| } | ||
| } | ||
|
||
|
|
||
| if options.Name == "" { | ||
| // get the function name for the passed workflow if there's | ||
| // no explicit name provided. | ||
| name, err := getFunctionName(w) | ||
| if err != nil { | ||
| return fmt.Errorf("failed to get workflow decorator: %v", err) | ||
| } | ||
| options.Name = name | ||
| } | ||
|
|
||
| err = ww.tasks.AddOrchestratorN(name, wrappedOrchestration) | ||
| return err | ||
| return ww.tasks.AddOrchestratorN(options.Name, wrappedOrchestration) | ||
| } | ||
|
|
||
| func wrapActivity(a Activity) task.Activity { | ||
|
|
@@ -136,17 +167,27 @@ func wrapActivity(a Activity) task.Activity { | |
| } | ||
|
|
||
| // RegisterActivity adds an activity function to the registry | ||
| func (ww *WorkflowWorker) RegisterActivity(a Activity) error { | ||
| func (ww *WorkflowWorker) RegisterActivity(a Activity, opts ...registerOption) error { | ||
| wrappedActivity := wrapActivity(a) | ||
|
|
||
| // get the function name for the passed activity | ||
| name, err := getFunctionName(a) | ||
| if err != nil { | ||
| return fmt.Errorf("failed to get activity decorator: %v", err) | ||
| options := registerOptions{} | ||
| for _, opt := range opts { | ||
| if err := opt(&options); err != nil { | ||
| return fmt.Errorf("failed processing options: %w", err) | ||
| } | ||
| } | ||
|
|
||
| if options.Name == "" { | ||
| // get the function name for the passed workflow if there's | ||
| // no explicit name provided. | ||
| name, err := getFunctionName(a) | ||
| if err != nil { | ||
| return fmt.Errorf("failed to get activity decorator: %v", err) | ||
| } | ||
| options.Name = name | ||
| } | ||
|
|
||
| err = ww.tasks.AddActivityN(name, wrappedActivity) | ||
| return err | ||
| return ww.tasks.AddActivityN(options.Name, wrappedActivity) | ||
| } | ||
|
|
||
| // Start initialises a non-blocking worker to handle workflows and activities registered | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since it's wholly within the workflow package I think
WithNamemakes sense, wdyt?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can do!
The main reason was that this same file has some worker options too, that were prefixed with
WorkerThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair point, I definitely think I should have added it as a wrapped function as it's probably never used other than in testing