go.uber.org/cadence@v1.2.9/worker/worker.go (about) 1 // Copyright (c) 2017-2020 Uber Technologies Inc. 2 // Portions of the Software are attributed to Copyright (c) 2020 Temporal Technologies Inc. 3 // 4 // Permission is hereby granted, free of charge, to any person obtaining a copy 5 // of this software and associated documentation files (the "Software"), to deal 6 // in the Software without restriction, including without limitation the rights 7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 // copies of the Software, and to permit persons to whom the Software is 9 // furnished to do so, subject to the following conditions: 10 // 11 // The above copyright notice and this permission notice shall be included in 12 // all copies or substantial portions of the Software. 13 // 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 // THE SOFTWARE. 21 22 // Package worker contains functions to manage lifecycle of a Cadence client side worker. 23 package worker 24 25 import ( 26 "context" 27 "io" 28 29 "go.uber.org/zap" 30 31 "go.uber.org/cadence/.gen/go/cadence/workflowserviceclient" 32 "go.uber.org/cadence/.gen/go/shared" 33 "go.uber.org/cadence/activity" 34 "go.uber.org/cadence/internal" 35 "go.uber.org/cadence/internal/common/auth" 36 "go.uber.org/cadence/workflow" 37 ) 38 39 type ( 40 // Worker hosts workflow and activity implementations. 41 // Use worker.New(...) to create an instance. 42 Worker interface { 43 Registry 44 45 // Start starts the worker in a non-blocking fashion 46 Start() error 47 // Run is a blocking start and cleans up resources when killed 48 // returns error only if it fails to start the worker 49 Run() error 50 // Stop cleans up any resources opened by worker 51 Stop() 52 } 53 54 // Registry exposes registration functions to consumers. 55 Registry interface { 56 WorkflowRegistry 57 ActivityRegistry 58 } 59 60 // WorkflowRegistry exposes workflow registration functions to consumers. 61 WorkflowRegistry interface { 62 // RegisterWorkflow - registers a workflow function with the worker. 63 // A workflow takes a workflow.Context and input and returns a (result, error) or just error. 64 // Examples: 65 // func sampleWorkflow(ctx workflow.Context, input []byte) (result []byte, err error) 66 // func sampleWorkflow(ctx workflow.Context, arg1 int, arg2 string) (result []byte, err error) 67 // func sampleWorkflow(ctx workflow.Context) (result []byte, err error) 68 // func sampleWorkflow(ctx workflow.Context, arg1 int) (result string, err error) 69 // Serialization of all primitive types, structures is supported ... except channels, functions, variadic, unsafe pointer. 70 // For global registration consider workflow.Register 71 // This method panics if workflowFunc doesn't comply with the expected format or tries to register the same workflow 72 RegisterWorkflow(w interface{}) 73 74 // RegisterWorkflowWithOptions registers the workflow function with options. 75 // The user can use options to provide an external name for the workflow or leave it empty if no 76 // external name is required. This can be used as 77 // worker.RegisterWorkflowWithOptions(sampleWorkflow, RegisterWorkflowOptions{}) 78 // worker.RegisterWorkflowWithOptions(sampleWorkflow, RegisterWorkflowOptions{Name: "foo"}) 79 // This method panics if workflowFunc doesn't comply with the expected format or tries to register the same workflow 80 // type name twice. Use workflow.RegisterOptions.DisableAlreadyRegisteredCheck to allow multiple registrations. 81 RegisterWorkflowWithOptions(w interface{}, options workflow.RegisterOptions) 82 } 83 84 // ActivityRegistry exposes activity registration functions to consumers. 85 ActivityRegistry interface { 86 // RegisterActivity - register an activity function or a pointer to a structure with the worker. 87 // An activity function takes a context and input and returns a (result, error) or just error. 88 // 89 // And activity struct is a structure with all its exported methods treated as activities. The default 90 // name of each activity is the method name. 91 // 92 // Examples: 93 // func sampleActivity(ctx context.Context, input []byte) (result []byte, err error) 94 // func sampleActivity(ctx context.Context, arg1 int, arg2 string) (result *customerStruct, err error) 95 // func sampleActivity(ctx context.Context) (err error) 96 // func sampleActivity() (result string, err error) 97 // func sampleActivity(arg1 bool) (result int, err error) 98 // func sampleActivity(arg1 bool) (err error) 99 // 100 // type Activities struct { 101 // // fields 102 // } 103 // func (a *Activities) SampleActivity1(ctx context.Context, arg1 int, arg2 string) (result *customerStruct, err error) { 104 // ... 105 // } 106 // 107 // func (a *Activities) SampleActivity2(ctx context.Context, arg1 int, arg2 *customerStruct) (result string, err error) { 108 // ... 109 // } 110 // 111 // Serialization of all primitive types, structures is supported ... except channels, functions, variadic, unsafe pointer. 112 // This method panics if activityFunc doesn't comply with the expected format or an activity with the same 113 // type name is registered more than once. 114 // For global registration consider activity.Register 115 RegisterActivity(a interface{}) 116 117 // RegisterActivityWithOptions registers the activity function or struct pointer with options. 118 // The user can use options to provide an external name for the activity or leave it empty if no 119 // external name is required. This can be used as 120 // worker.RegisterActivityWithOptions(barActivity, RegisterActivityOptions{}) 121 // worker.RegisterActivityWithOptions(barActivity, RegisterActivityOptions{Name: "barExternal"}) 122 // When registering the structure that implements activities the name is used as a prefix that is 123 // prepended to the activity method name. 124 // worker.RegisterActivityWithOptions(&Activities{ ... }, RegisterActivityOptions{Name: "MyActivities_"}) 125 // To override each name of activities defined through a structure register the methods one by one: 126 // activities := &Activities{ ... } 127 // worker.RegisterActivityWithOptions(activities.SampleActivity1, RegisterActivityOptions{Name: "Sample1"}) 128 // worker.RegisterActivityWithOptions(activities.SampleActivity2, RegisterActivityOptions{Name: "Sample2"}) 129 // See RegisterActivity function for more info. 130 // The other use of options is to disable duplicated activity registration check 131 // which might be useful for integration tests. 132 // worker.RegisterActivityWithOptions(barActivity, RegisterActivityOptions{DisableAlreadyRegisteredCheck: true}) 133 RegisterActivityWithOptions(a interface{}, options activity.RegisterOptions) 134 } 135 136 // WorkflowReplayer supports replaying a workflow from its event history. 137 // Use for troubleshooting and backwards compatibility unit tests. 138 // For example if a workflow failed in production then its history can be downloaded through UI or CLI 139 // and replayed in a debugger as many times as necessary. 140 // Use this class to create unit tests that check if workflow changes are backwards compatible. 141 // It is important to maintain backwards compatibility through use of workflow.GetVersion 142 // to ensure that new deployments are not going to break open workflows. 143 WorkflowReplayer interface { 144 WorkflowRegistry 145 ActivityRegistry 146 147 // ReplayWorkflowHistory executes a single decision task for the given json history file. 148 // Use for testing the backwards compatibility of code changes and troubleshooting workflows in a debugger. 149 // The logger is an optional parameter. Defaults to the noop logger. 150 ReplayWorkflowHistory(logger *zap.Logger, history *shared.History) error 151 152 // ReplayWorkflowHistoryFromJSONFile executes a single decision task for the json history file downloaded from the cli. 153 // To download the history file: cadence workflow showid <workflow_id> -of <output_filename> 154 // See https://github.com/uber/cadence/blob/master/tools/cli/README.md for full documentation 155 // Use for testing the backwards compatibility of code changes and troubleshooting workflows in a debugger. 156 // The logger is an optional parameter. Defaults to the noop logger. 157 // 158 // Deprecated: prefer ReplayWorkflowHistoryFromJSON 159 ReplayWorkflowHistoryFromJSONFile(logger *zap.Logger, jsonfileName string) error 160 161 // ReplayPartialWorkflowHistoryFromJSONFile executes a single decision task for the json history file upto provided 162 // lastEventID(inclusive), downloaded from the cli. 163 // To download the history file: cadence workflow showid <workflow_id> -of <output_filename> 164 // See https://github.com/uber/cadence/blob/master/tools/cli/README.md for full documentation 165 // Use for testing the backwards compatibility of code changes and troubleshooting workflows in a debugger. 166 // The logger is an optional parameter. Defaults to the noop logger. 167 // 168 // Deprecated: prefer ReplayPartialWorkflowHistoryFromJSON 169 ReplayPartialWorkflowHistoryFromJSONFile(logger *zap.Logger, jsonfileName string, lastEventID int64) error 170 171 // ReplayWorkflowExecution loads a workflow execution history from the Cadence service and executes a single decision task for it. 172 // Use for testing the backwards compatibility of code changes and troubleshooting workflows in a debugger. 173 // The logger is the only optional parameter. Defaults to the noop logger. 174 ReplayWorkflowExecution(ctx context.Context, service workflowserviceclient.Interface, logger *zap.Logger, domain string, execution workflow.Execution) error 175 176 // ReplayWorkflowHistoryFromJSON executes a single decision task for the json history file downloaded from the cli. 177 // To download the history file: 178 // cadence workflow showid <workflow_id> -of <output_filename> 179 // See https://github.com/uber/cadence/blob/master/tools/cli/README.md for full documentation 180 // Use for testing the backwards compatibility of code changes and troubleshooting workflows in a debugger. 181 // The logger is an optional parameter. Defaults to the noop logger. 182 ReplayWorkflowHistoryFromJSON(logger *zap.Logger, reader io.Reader) error 183 184 // ReplayPartialWorkflowHistoryFromJSON executes a single decision task for the json history file upto provided 185 // lastEventID(inclusive), downloaded from the cli. 186 // To download the history file: 187 // cadence workflow showid <workflow_id> -of <output_filename> 188 // See https://github.com/uber/cadence/blob/master/tools/cli/README.md for full documentation 189 // Use for testing the backwards compatibility of code changes and troubleshooting workflows in a debugger. 190 // The logger is an optional parameter. Defaults to the noop logger. 191 ReplayPartialWorkflowHistoryFromJSON(logger *zap.Logger, reader io.Reader, lastEventID int64) error 192 } 193 194 // WorkflowShadower retrieves and replays workflow history from Cadence service to determine if there's any nondeterministic changes in the workflow definition 195 WorkflowShadower interface { 196 WorkflowRegistry 197 198 Run() error 199 } 200 201 // Options is used to configure a worker instance. 202 Options = internal.WorkerOptions 203 204 // ShadowOptions is used to configure a WorkflowShadower. 205 ShadowOptions = internal.ShadowOptions 206 // ShadowMode is an enum for configuring if shadowing should continue after all workflows matches the WorkflowQuery have been replayed. 207 ShadowMode = internal.ShadowMode 208 // TimeFilter represents a time range through the min and max timestamp 209 TimeFilter = internal.TimeFilter 210 // ShadowExitCondition configures when the workflow shadower should exit. 211 // If not specified shadower will exit after replaying all workflows satisfying the visibility query. 212 ShadowExitCondition = internal.ShadowExitCondition 213 214 // ReplayOptions is used to configure the replay decision task worker. 215 ReplayOptions = internal.ReplayOptions 216 217 // NonDeterministicWorkflowPolicy is an enum for configuring how client's decision task handler deals with 218 // mismatched history events (presumably arising from non-deterministic workflow definitions). 219 NonDeterministicWorkflowPolicy = internal.NonDeterministicWorkflowPolicy 220 221 // AuthorizationProvider is the interface that contains the method to get the auth token 222 AuthorizationProvider = auth.AuthorizationProvider 223 224 // OAuthConfig allows to configure external OAuth token provider. 225 OAuthConfig = internal.OAuthAuthorizerConfig 226 ) 227 228 const ( 229 // NonDeterministicWorkflowPolicyBlockWorkflow is the default policy for handling detected non-determinism. 230 // This option simply logs to console with an error message that non-determinism is detected, but 231 // does *NOT* reply anything back to the server. 232 // It is chosen as default for backward compatibility reasons because it preserves the old behavior 233 // for handling non-determinism that we had before NonDeterministicWorkflowPolicy type was added to 234 // allow more configurability. 235 NonDeterministicWorkflowPolicyBlockWorkflow = internal.NonDeterministicWorkflowPolicyBlockWorkflow 236 // NonDeterministicWorkflowPolicyFailWorkflow behaves exactly the same as Ignore, up until the very 237 // end of processing a decision task. 238 // Whereas default does *NOT* reply anything back to the server, fail workflow replies back with a request 239 // to fail the workflow execution. 240 NonDeterministicWorkflowPolicyFailWorkflow = internal.NonDeterministicWorkflowPolicyFailWorkflow 241 ) 242 243 const ( 244 // ShadowModeNormal is the default mode for workflow shadowing. 245 // Shadowing will complete after all workflows matches WorkflowQuery have been replayed. 246 ShadowModeNormal = internal.ShadowModeNormal 247 // ShadowModeContinuous mode will start a new round of shadowing 248 // after all workflows matches WorkflowQuery have been replayed. 249 // There will be a 5 min wait period between each round, 250 // currently this wait period is not configurable. 251 // Shadowing will complete only when ExitCondition is met. 252 // ExitCondition must be specified when using this mode 253 ShadowModeContinuous = internal.ShadowModeContinuous 254 ) 255 256 // New creates an instance of worker for managing workflow and activity executions. 257 // 258 // service - thrift connection to the cadence server 259 // domain - the name of the cadence domain 260 // taskList - is the task list name you use to identify your client worker, also 261 // identifies group of workflow and activity implementations that are 262 // hosted by a single worker process 263 // options - configure any worker specific options like logger, metrics, identity 264 func New( 265 service workflowserviceclient.Interface, 266 domain string, 267 taskList string, 268 options Options, 269 ) Worker { 270 return internal.NewWorker(service, domain, taskList, options) 271 } 272 273 // NewWorkflowReplayer creates a WorkflowReplayer instance. 274 func NewWorkflowReplayer() WorkflowReplayer { 275 return internal.NewWorkflowReplayer() 276 } 277 278 // NewWorkflowReplayerWithOptions creates an instance of the WorkflowReplayer 279 // with provided replay worker options 280 func NewWorkflowReplayerWithOptions( 281 options ReplayOptions, 282 ) WorkflowReplayer { 283 return internal.NewWorkflowReplayerWithOptions(options) 284 } 285 286 // NewWorkflowShadower creates a WorkflowShadower instance. 287 func NewWorkflowShadower( 288 service workflowserviceclient.Interface, 289 domain string, 290 shadowOptions ShadowOptions, 291 replayOptions ReplayOptions, 292 logger *zap.Logger, 293 ) (WorkflowShadower, error) { 294 return internal.NewWorkflowShadower(service, domain, shadowOptions, replayOptions, logger) 295 } 296 297 // EnableVerboseLogging enable or disable verbose logging of internal Cadence library components. 298 // Most customers don't need this feature, unless advised by the Cadence team member. 299 // Also there is no guarantee that this API is not going to change. 300 func EnableVerboseLogging(enable bool) { 301 internal.EnableVerboseLogging(enable) 302 } 303 304 // ReplayWorkflowHistory executes a single decision task for the given json history file. 305 // Use for testing the backwards compatibility of code changes and troubleshooting workflows in a debugger. 306 // The logger is an optional parameter. Defaults to the noop logger. 307 func ReplayWorkflowHistory(logger *zap.Logger, history *shared.History) error { 308 return internal.ReplayWorkflowHistory(logger, history) 309 } 310 311 // ReplayWorkflowHistoryFromJSONFile executes a single decision task for the json history file downloaded from the cli. 312 // To download the history file: cadence workflow showid <workflow_id> -of <output_filename> 313 // See https://github.com/uber/cadence/blob/master/tools/cli/README.md for full documentation 314 // Use for testing the backwards compatibility of code changes and troubleshooting workflows in a debugger. 315 // The logger is an optional parameter. Defaults to the noop logger. 316 func ReplayWorkflowHistoryFromJSONFile(logger *zap.Logger, jsonfileName string) error { 317 return internal.ReplayWorkflowHistoryFromJSONFile(logger, jsonfileName) 318 } 319 320 // ReplayPartialWorkflowHistoryFromJSONFile executes a single decision task for the json history file upto provided 321 // // lastEventID(inclusive), downloaded from the cli. 322 // To download the history file: cadence workflow showid <workflow_id> -of <output_filename> 323 // See https://github.com/uber/cadence/blob/master/tools/cli/README.md for full documentation 324 // Use for testing the backwards compatibility of code changes and troubleshooting workflows in a debugger. 325 // The logger is an optional parameter. Defaults to the noop logger. 326 func ReplayPartialWorkflowHistoryFromJSONFile(logger *zap.Logger, jsonfileName string, lastEventID int64) error { 327 return internal.ReplayPartialWorkflowHistoryFromJSONFile(logger, jsonfileName, lastEventID) 328 } 329 330 // ReplayWorkflowExecution loads a workflow execution history from the Cadence service and executes a single decision task for it. 331 // Use for testing the backwards compatibility of code changes and troubleshooting workflows in a debugger. 332 // The logger is the only optional parameter. Defaults to the noop logger. 333 func ReplayWorkflowExecution(ctx context.Context, service workflowserviceclient.Interface, logger *zap.Logger, domain string, execution workflow.Execution) error { 334 return internal.ReplayWorkflowExecution(ctx, service, logger, domain, execution) 335 } 336 337 // SetStickyWorkflowCacheSize sets the cache size for sticky workflow cache. Sticky workflow execution is the affinity 338 // between decision tasks of a specific workflow execution to a specific worker. The affinity is set if sticky execution 339 // is enabled via Worker.Options (It is enabled by default unless disabled explicitly). The benefit of sticky execution 340 // is that workflow does not have to reconstruct the state by replaying from beginning of history events. But the cost 341 // is it consumes more memory as it rely on caching workflow execution's running state on the worker. The cache is shared 342 // between workers running within same process. This must be called before any worker is started. If not called, the 343 // default size of 10K (might change in future) will be used. 344 func SetStickyWorkflowCacheSize(cacheSize int) { 345 internal.SetStickyWorkflowCacheSize(cacheSize) 346 } 347 348 // SetBinaryChecksum sets the identifier of the binary(aka BinaryChecksum). 349 // The identifier is mainly used in recording reset points when respondDecisionTaskCompleted. For each workflow, the very first 350 // decision completed by a binary will be associated as a auto-reset point for the binary. So that when a customer wants to 351 // mark the binary as bad, the workflow will be reset to that point -- which means workflow will forget all progress generated 352 // by the binary. 353 // On another hand, once the binary is marked as bad, the bad binary cannot poll decision and make any progress any more. 354 func SetBinaryChecksum(checksum string) { 355 internal.SetBinaryChecksum(checksum) 356 } 357 358 // NewAdminJwtAuthorizationProvider creates a JwtAuthorizationProvider instance. 359 func NewAdminJwtAuthorizationProvider(privateKey []byte) AuthorizationProvider { 360 return internal.NewAdminJwtAuthorizationProvider(privateKey) 361 } 362 363 // NewOAuthAuthorizationProvider asks for a token from external OAuth provider 364 func NewOAuthAuthorizationProvider(config OAuthConfig) AuthorizationProvider { 365 return internal.NewOAuthAuthorizationProvider(config) 366 } 367 368 // AugmentWorkerOptions fill all unset worker Options fields with their default values 369 // Use as getter for default worker options 370 func AugmentWorkerOptions(options Options) Options { 371 return internal.AugmentWorkerOptions(options) 372 }