Class: Temporalio::Workflow::Definition

Inherits:
Object
  • Object
show all
Defined in:
lib/temporalio/workflow/definition.rb

Overview

Base class for all workflows.

Workflows are instances of this class and must implement #execute. Inside the workflow code, class methods on Temporalio::Workflow can be used.

By default, the workflow is named as its unqualified class name. This can be customized with Definition.workflow_name.

Defined Under Namespace

Classes: Info, Query, Signal, Update

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.workflow_arg_hint(*hints) ⇒ Object (protected)

Add workflow hints to be passed to converter for workflow args.

Parameters:

  • hints (Array<Object>)

    Hints to add.



53
54
55
56
# File 'lib/temporalio/workflow/definition.rb', line 53

def workflow_arg_hint(*hints)
  @workflow_arg_hints ||= []
  @workflow_arg_hints.concat(hints)
end

.workflow_dynamic(value = true) ⇒ Object (protected)

Set a workflow as dynamic. Dynamic workflows do not have names and handle any workflow that is not otherwise registered. A worker can only have one dynamic workflow. It is often useful to use workflow_raw_args with this.

Parameters:

  • value (Boolean) (defaults to: true)

    Whether the workflow is dynamic.



37
38
39
# File 'lib/temporalio/workflow/definition.rb', line 37

def workflow_dynamic(value = true) # rubocop:disable Style/OptionalBooleanParameter
  @workflow_dynamic = value
end

.workflow_dynamic_optionsObject (protected)

Mark the next method as returning some dynamic configuraion.

Because dynamic workflows may conceptually represent more than one workflow type, it may be desirable to have different settings for fields that would normally be passed to ‘workflow_xxx` setters, but vary based on the workflow type name or other information available in the workflow’s context. This function will be called after the workflow’s ‘initialize`, if it has one, but before the workflow’s ‘execute` method.

The method must only take self as a parameter, and any values set in the class it returns will override those provided to other ‘workflow_xxx` setters.

Cannot be specified on non-dynamic workflows.



234
235
236
237
238
# File 'lib/temporalio/workflow/definition.rb', line 234

def workflow_dynamic_options
  raise 'Dynamic options method can only be set on workflows using `workflow_dynamic`' unless @workflow_dynamic

  self.pending_handler_details = { type: :dynamic_options }
end

.workflow_failure_exception_type(*types) ⇒ Object (protected)

Configure workflow failure exception types. This sets the types of exceptions that, if a workflow-thrown exception extends, will cause the workflow/update to fail instead of suspending the workflow via task failure. These are applied in addition to the worker option. If Exception is set, it effectively will fail a workflow/update in all user exception cases.

Parameters:

  • types (Array<Class<Exception>>)

    Exception types to turn into workflow failures.



71
72
73
74
75
76
77
# File 'lib/temporalio/workflow/definition.rb', line 71

def workflow_failure_exception_type(*types)
  types.each do |t|
    raise ArgumentError, 'All types must classes inheriting Exception' unless t.is_a?(Class) && t <= Exception
  end
  @workflow_failure_exception_types ||= []
  @workflow_failure_exception_types.concat(types)
end

.workflow_init(value = true) ⇒ Object (protected)

Mark an ‘initialize` as needing the workflow start arguments. Otherwise, `initialize` must accept no required arguments. This must be placed above the `initialize` method or it will fail.

Parameters:

  • value (Boolean) (defaults to: true)

    Whether the start parameters will be passed to ‘initialize`.



122
123
124
# File 'lib/temporalio/workflow/definition.rb', line 122

def workflow_init(value = true) # rubocop:disable Style/OptionalBooleanParameter
  self.pending_handler_details = { type: :init, value: }
end

.workflow_name(workflow_name) ⇒ Object (protected)

Customize the workflow name. By default the workflow is named the unqualified class name of the class provided to the worker.

Parameters:

  • workflow_name (String, Symbol)

    Name to use.



23
24
25
26
27
28
29
30
# File 'lib/temporalio/workflow/definition.rb', line 23

def workflow_name(workflow_name)
  if !workflow_name.is_a?(Symbol) && !workflow_name.is_a?(String)
    raise ArgumentError,
          'Workflow name must be a symbol or string'
  end

  @workflow_name = workflow_name.to_s
end

.workflow_query(name: nil, description: nil, dynamic: false, raw_args: false, arg_hints: nil, result_hint: nil) ⇒ Object (protected)

Mark the next method as a workflow query with a default name as the name of the method. Queries can not have any side effects, meaning they should never mutate state or try to wait on anything.

Parameters:

  • name (String, Symbol, nil) (defaults to: nil)

    Override the default name.

  • description (String, nil) (defaults to: nil)

    Description for this handler that may appear in CLI/UI. This is currently experimental.

  • dynamic (Boolean) (defaults to: false)

    If true, make the query dynamic. This means it receives all other queries without handlers. This cannot have a name override since it is nameless. The first parameter will be the name. Often it is useful to have the second parameter be ‘*args` and `raw_args` be true.

  • raw_args (Boolean) (defaults to: false)

    If true, does not convert arguments, but instead provides each argument as Converters::RawValue which is a raw payload wrapper, convertible with Temporalio::Workflow.payload_converter.

  • arg_hints (Object, Array<Object>, nil) (defaults to: nil)

    Argument hint(s) for the query.

  • result_hint (Object, nil) (defaults to: nil)

    Result hint for the query.



168
169
170
171
172
173
174
175
176
177
178
179
180
# File 'lib/temporalio/workflow/definition.rb', line 168

def workflow_query(
  name: nil,
  description: nil,
  dynamic: false,
  raw_args: false,
  arg_hints: nil,
  result_hint: nil
)
  raise 'Cannot provide name if dynamic is true' if name && dynamic

  self.pending_handler_details = { type: :query, name:, description:, dynamic:, raw_args:,
                                   arg_hints: Array(arg_hints), result_hint: }
end

.workflow_query_attr_reader(*attr_names, description: nil) ⇒ Object (protected)

Expose an attribute as a method and as a query. A ‘workflow_query_attr_reader :foo` is the equivalent of: “` workflow_query def foo

@foo

end “‘ This means it is a superset of `attr_reader“ and will not work if also using `attr_reader` or `attr_accessor`. If a writer is needed alongside this, use `attr_writer`.

Parameters:

  • attr_names (Array<Symbol>)

    Attributes to expose.

  • description (String, nil) (defaults to: nil)

    Description that may appear in CLI/UI, applied to each query handler implicitly created. This is currently experimental.



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/temporalio/workflow/definition.rb', line 92

def workflow_query_attr_reader(*attr_names, description: nil)
  @workflow_queries ||= {}
  attr_names.each do |attr_name|
    raise 'Expected attr to be a symbol' unless attr_name.is_a?(Symbol)

    if method_defined?(attr_name, false)
      raise 'Method already defined for this attr name. ' \
            'Note that a workflow_query_attr_reader includes attr_reader behavior. ' \
            'If you also want a writer for this attribute, use a separate attr_writer.'
    end

    # Just run this as if done manually
    workflow_query(description:)
    define_method(attr_name) { instance_variable_get("@#{attr_name}") }
  end
end

.workflow_raw_args(value = true) ⇒ Object (protected)

Have workflow arguments delivered to ‘execute` (and `initialize` if workflow_init in use) as Converters::RawValues. These are wrappers for the raw payloads that have not been converted to types (but they have been decoded by the codec if present). They can be converted with Temporalio::Workflow.payload_converter.

Parameters:

  • value (Boolean) (defaults to: true)

    Whether the workflow accepts raw arguments.



46
47
48
# File 'lib/temporalio/workflow/definition.rb', line 46

def workflow_raw_args(value = true) # rubocop:disable Style/OptionalBooleanParameter
  @workflow_raw_args = value
end

.workflow_result_hint(hint) ⇒ Object (protected)

Set workflow result hint to be passed to converter for workflow result.

Parameters:

  • hint (Object)

    Hint to set.



61
62
63
# File 'lib/temporalio/workflow/definition.rb', line 61

def workflow_result_hint(hint)
  @workflow_result_hint = hint
end

.workflow_signal(name: nil, description: nil, dynamic: false, raw_args: false, unfinished_policy: HandlerUnfinishedPolicy::WARN_AND_ABANDON, arg_hints: nil) ⇒ Object (protected)

Mark the next method as a workflow signal with a default name as the name of the method. Signals cannot return values.

Parameters:

  • name (String, Symbol, nil) (defaults to: nil)

    Override the default name.

  • description (String, nil) (defaults to: nil)

    Description for this handler that may appear in CLI/UI. This is currently experimental.

  • dynamic (Boolean) (defaults to: false)

    If true, make the signal dynamic. This means it receives all other signals without handlers. This cannot have a name override since it is nameless. The first parameter will be the name. Often it is useful to have the second parameter be ‘*args` and `raw_args` be true.

  • raw_args (Boolean) (defaults to: false)

    If true, does not convert arguments, but instead provides each argument as Converters::RawValue which is a raw payload wrapper, convertible with Temporalio::Workflow.payload_converter.

  • unfinished_policy (HandlerUnfinishedPolicy) (defaults to: HandlerUnfinishedPolicy::WARN_AND_ABANDON)

    How to treat unfinished handlers if they are still running when the workflow ends. The default warns, but this can be disabled.

  • arg_hints (Array<Object>, nil) (defaults to: nil)

    Argument hint(s) for the signal.



140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/temporalio/workflow/definition.rb', line 140

def workflow_signal(
  name: nil,
  description: nil,
  dynamic: false,
  raw_args: false,
  unfinished_policy: HandlerUnfinishedPolicy::WARN_AND_ABANDON,
  arg_hints: nil
)
  raise 'Cannot provide name if dynamic is true' if name && dynamic

  self.pending_handler_details =
    { type: :signal, name:, description:, dynamic:, raw_args:, unfinished_policy:,
      arg_hints: Array(arg_hints) }
end

.workflow_update(name: nil, description: nil, dynamic: false, raw_args: false, unfinished_policy: HandlerUnfinishedPolicy::WARN_AND_ABANDON, arg_hints: nil, result_hint: nil) ⇒ Object (protected)

Mark the next method as a workflow update with a default name as the name of the method. Updates can return values. Separate validation methods can be provided via workflow_update_validator.

Parameters:

  • name (String, Symbol, nil) (defaults to: nil)

    Override the default name.

  • description (String, nil) (defaults to: nil)

    Description for this handler that may appear in CLI/UI. This is currently experimental.

  • dynamic (Boolean) (defaults to: false)

    If true, make the update dynamic. This means it receives all other updates without handlers. This cannot have a name override since it is nameless. The first parameter will be the name. Often it is useful to have the second parameter be ‘*args` and `raw_args` be true.

  • raw_args (Boolean) (defaults to: false)

    If true, does not convert arguments, but instead provides each argument as Converters::RawValue which is a raw payload wrapper, convertible with Temporalio::Workflow.payload_converter.

  • unfinished_policy (HandlerUnfinishedPolicy) (defaults to: HandlerUnfinishedPolicy::WARN_AND_ABANDON)

    How to treat unfinished handlers if they are still running when the workflow ends. The default warns, but this can be disabled.

  • arg_hints (Object, Array<Object>, nil) (defaults to: nil)

    Argument hint(s) for the update.

  • result_hint (Object, nil) (defaults to: nil)

    Result hint for the update.



197
198
199
200
201
202
203
204
205
206
207
208
209
210
# File 'lib/temporalio/workflow/definition.rb', line 197

def workflow_update(
  name: nil,
  description: nil,
  dynamic: false,
  raw_args: false,
  unfinished_policy: HandlerUnfinishedPolicy::WARN_AND_ABANDON,
  arg_hints: nil,
  result_hint: nil
)
  raise 'Cannot provide name if dynamic is true' if name && dynamic

  self.pending_handler_details = { type: :update, name:, description:, dynamic:, raw_args:, unfinished_policy:,
                                   arg_hints: Array(arg_hints), result_hint: }
end

.workflow_update_validator(update_method) ⇒ Object (protected)

Mark the next method as a workflow update validator to the given update method. The validator is expected to have the exact same parameter signature. It will run before an update and if it raises an exception, the update will be rejected, possibly before even reaching history. Validators cannot have any side effects or do any waiting, and they do not return values.

Parameters:

  • update_method (Symbol)

    Name of the update method.



218
219
220
# File 'lib/temporalio/workflow/definition.rb', line 218

def workflow_update_validator(update_method)
  self.pending_handler_details = { type: :update_validator, update_method: }
end

.workflow_versioning_behavior(behavior) ⇒ Object (protected)

Set the versioning behavior of this workflow.

WARNING: This method is experimental and may change in future versions.

Parameters:



114
115
116
# File 'lib/temporalio/workflow/definition.rb', line 114

def workflow_versioning_behavior(behavior)
  @versioning_behavior = behavior
end

Instance Method Details

#execute(*args) ⇒ Object

Execute the workflow. This is the primary workflow method. The workflow is completed when this method completes. This must be implemented by all workflows.

Raises:

  • (NotImplementedError)


497
498
499
# File 'lib/temporalio/workflow/definition.rb', line 497

def execute(*args)
  raise NotImplementedError, 'Workflow did not implement "execute"'
end