temporal-ruby 0.0.0 → 0.0.1.pre.pre1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +19 -42
  3. data/lib/gen/temporal/api/command/v1/message_pb.rb +146 -0
  4. data/lib/gen/temporal/api/common/v1/message_pb.rb +67 -0
  5. data/lib/gen/temporal/api/enums/v1/command_type_pb.rb +35 -0
  6. data/lib/gen/temporal/api/enums/v1/common_pb.rb +34 -0
  7. data/lib/gen/temporal/api/enums/v1/event_type_pb.rb +62 -0
  8. data/lib/gen/temporal/api/enums/v1/failed_cause_pb.rb +60 -0
  9. data/lib/gen/temporal/api/enums/v1/namespace_pb.rb +31 -0
  10. data/lib/gen/temporal/api/enums/v1/query_pb.rb +31 -0
  11. data/lib/gen/temporal/api/enums/v1/task_queue_pb.rb +30 -0
  12. data/lib/gen/temporal/api/enums/v1/workflow_pb.rb +82 -0
  13. data/lib/gen/temporal/api/errordetails/v1/message_pb.rb +55 -0
  14. data/lib/gen/temporal/api/failure/v1/message_pb.rb +81 -0
  15. data/lib/gen/temporal/api/filter/v1/message_pb.rb +38 -0
  16. data/lib/gen/temporal/api/history/v1/message_pb.rb +423 -0
  17. data/lib/gen/temporal/api/namespace/v1/message_pb.rb +55 -0
  18. data/lib/gen/temporal/api/query/v1/message_pb.rb +36 -0
  19. data/lib/gen/temporal/api/replication/v1/message_pb.rb +27 -0
  20. data/lib/gen/temporal/api/taskqueue/v1/message_pb.rb +60 -0
  21. data/lib/gen/temporal/api/version/v1/message_pb.rb +28 -0
  22. data/lib/gen/temporal/api/workflow/v1/message_pb.rb +83 -0
  23. data/lib/gen/temporal/api/workflowservice/v1/request_response_pb.rb +538 -0
  24. data/lib/gen/temporal/api/workflowservice/v1/service_pb.rb +19 -0
  25. data/lib/gen/temporal/api/workflowservice/v1/service_services_pb.rb +223 -0
  26. data/lib/temporal-ruby.rb +1 -0
  27. data/lib/temporal.rb +137 -0
  28. data/lib/temporal/activity.rb +33 -0
  29. data/lib/temporal/activity/async_token.rb +34 -0
  30. data/lib/temporal/activity/context.rb +64 -0
  31. data/lib/temporal/activity/poller.rb +79 -0
  32. data/lib/temporal/activity/task_processor.rb +78 -0
  33. data/lib/temporal/activity/workflow_convenience_methods.rb +41 -0
  34. data/lib/temporal/client.rb +21 -0
  35. data/lib/temporal/client/errors.rb +8 -0
  36. data/lib/temporal/client/grpc_client.rb +345 -0
  37. data/lib/temporal/client/serializer.rb +31 -0
  38. data/lib/temporal/client/serializer/base.rb +23 -0
  39. data/lib/temporal/client/serializer/cancel_timer.rb +19 -0
  40. data/lib/temporal/client/serializer/complete_workflow.rb +20 -0
  41. data/lib/temporal/client/serializer/fail_workflow.rb +20 -0
  42. data/lib/temporal/client/serializer/failure.rb +29 -0
  43. data/lib/temporal/client/serializer/payload.rb +25 -0
  44. data/lib/temporal/client/serializer/record_marker.rb +23 -0
  45. data/lib/temporal/client/serializer/request_activity_cancellation.rb +19 -0
  46. data/lib/temporal/client/serializer/schedule_activity.rb +53 -0
  47. data/lib/temporal/client/serializer/start_child_workflow.rb +51 -0
  48. data/lib/temporal/client/serializer/start_timer.rb +20 -0
  49. data/lib/temporal/concerns/executable.rb +37 -0
  50. data/lib/temporal/concerns/typed.rb +40 -0
  51. data/lib/temporal/configuration.rb +44 -0
  52. data/lib/temporal/errors.rb +38 -0
  53. data/lib/temporal/executable_lookup.rb +25 -0
  54. data/lib/temporal/execution_options.rb +35 -0
  55. data/lib/temporal/json.rb +18 -0
  56. data/lib/temporal/metadata.rb +68 -0
  57. data/lib/temporal/metadata/activity.rb +27 -0
  58. data/lib/temporal/metadata/base.rb +17 -0
  59. data/lib/temporal/metadata/workflow.rb +22 -0
  60. data/lib/temporal/metadata/workflow_task.rb +25 -0
  61. data/lib/temporal/metrics.rb +37 -0
  62. data/lib/temporal/metrics_adapters/log.rb +33 -0
  63. data/lib/temporal/metrics_adapters/null.rb +9 -0
  64. data/lib/temporal/middleware/chain.rb +30 -0
  65. data/lib/temporal/middleware/entry.rb +9 -0
  66. data/lib/temporal/retry_policy.rb +27 -0
  67. data/lib/temporal/saga/concern.rb +23 -0
  68. data/lib/temporal/saga/result.rb +22 -0
  69. data/lib/temporal/saga/saga.rb +24 -0
  70. data/lib/temporal/testing.rb +50 -0
  71. data/lib/temporal/testing/future_registry.rb +27 -0
  72. data/lib/temporal/testing/local_activity_context.rb +17 -0
  73. data/lib/temporal/testing/local_workflow_context.rb +178 -0
  74. data/lib/temporal/testing/temporal_override.rb +121 -0
  75. data/lib/temporal/testing/workflow_execution.rb +44 -0
  76. data/lib/temporal/testing/workflow_override.rb +36 -0
  77. data/lib/temporal/thread_local_context.rb +14 -0
  78. data/lib/temporal/thread_pool.rb +63 -0
  79. data/lib/temporal/types.rb +7 -0
  80. data/lib/temporal/uuid.rb +19 -0
  81. data/lib/temporal/version.rb +1 -1
  82. data/lib/temporal/worker.rb +88 -0
  83. data/lib/temporal/workflow.rb +42 -0
  84. data/lib/temporal/workflow/command.rb +39 -0
  85. data/lib/temporal/workflow/command_state_machine.rb +48 -0
  86. data/lib/temporal/workflow/context.rb +243 -0
  87. data/lib/temporal/workflow/convenience_methods.rb +34 -0
  88. data/lib/temporal/workflow/dispatcher.rb +31 -0
  89. data/lib/temporal/workflow/execution_info.rb +51 -0
  90. data/lib/temporal/workflow/executor.rb +45 -0
  91. data/lib/temporal/workflow/future.rb +77 -0
  92. data/lib/temporal/workflow/history.rb +76 -0
  93. data/lib/temporal/workflow/history/event.rb +69 -0
  94. data/lib/temporal/workflow/history/event_target.rb +75 -0
  95. data/lib/temporal/workflow/history/window.rb +40 -0
  96. data/lib/temporal/workflow/poller.rb +67 -0
  97. data/lib/temporal/workflow/replay_aware_logger.rb +36 -0
  98. data/lib/temporal/workflow/state_manager.rb +342 -0
  99. data/lib/temporal/workflow/task_processor.rb +78 -0
  100. data/rbi/temporal-ruby.rbi +43 -0
  101. data/temporal.gemspec +10 -2
  102. metadata +186 -6
@@ -0,0 +1,64 @@
1
+ # This context class is available in the activity implementation
2
+ # and provides context and methods for interacting with Temporal
3
+ #
4
+ require 'temporal/uuid'
5
+ require 'temporal/activity/async_token'
6
+
7
+ module Temporal
8
+ class Activity
9
+ class Context
10
+ def initialize(client, metadata)
11
+ @client = client
12
+ @metadata = metadata
13
+ @async = false
14
+ end
15
+
16
+ def async
17
+ @async = true
18
+ end
19
+
20
+ def async?
21
+ @async
22
+ end
23
+
24
+ def async_token
25
+ AsyncToken.encode(
26
+ metadata.namespace,
27
+ metadata.id,
28
+ metadata.workflow_id,
29
+ metadata.workflow_run_id
30
+ )
31
+ end
32
+
33
+ def heartbeat(details = nil)
34
+ logger.debug('Activity heartbeat')
35
+ client.record_activity_task_heartbeat(task_token: task_token, details: details)
36
+ end
37
+
38
+ def logger
39
+ Temporal.logger
40
+ end
41
+
42
+ def run_idem
43
+ UUID.v5(metadata.workflow_run_id.to_s, metadata.id.to_s)
44
+ end
45
+ alias idem run_idem
46
+
47
+ def workflow_idem
48
+ UUID.v5(metadata.workflow_id.to_s, metadata.id.to_s)
49
+ end
50
+
51
+ def headers
52
+ metadata.headers
53
+ end
54
+
55
+ private
56
+
57
+ attr_reader :client, :metadata
58
+
59
+ def task_token
60
+ metadata.task_token
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,79 @@
1
+ require 'temporal/client'
2
+ require 'temporal/thread_pool'
3
+ require 'temporal/middleware/chain'
4
+ require 'temporal/activity/task_processor'
5
+
6
+ module Temporal
7
+ class Activity
8
+ class Poller
9
+ THREAD_POOL_SIZE = 20
10
+
11
+ def initialize(namespace, task_queue, activity_lookup, middleware = [])
12
+ @namespace = namespace
13
+ @task_queue = task_queue
14
+ @activity_lookup = activity_lookup
15
+ @middleware = middleware
16
+ @shutting_down = false
17
+ end
18
+
19
+ def start
20
+ @shutting_down = false
21
+ @thread = Thread.new(&method(:poll_loop))
22
+ end
23
+
24
+ def stop
25
+ @shutting_down = true
26
+ Thread.new { Temporal.logger.info('Shutting down activity poller') }.join
27
+ end
28
+
29
+ def wait
30
+ thread.join
31
+ end
32
+
33
+ private
34
+
35
+ attr_reader :namespace, :task_queue, :activity_lookup, :middleware, :thread
36
+
37
+ def client
38
+ @client ||= Temporal::Client.generate
39
+ end
40
+
41
+ def shutting_down?
42
+ @shutting_down
43
+ end
44
+
45
+ def poll_loop
46
+ loop do
47
+ thread_pool.wait_for_available_threads
48
+
49
+ return if shutting_down?
50
+
51
+ Temporal.logger.debug("Polling activity task queue (#{namespace} / #{task_queue})")
52
+
53
+ task = poll_for_task
54
+ next unless task&.activity_type
55
+
56
+ thread_pool.schedule { process(task) }
57
+ end
58
+ end
59
+
60
+ def poll_for_task
61
+ client.poll_activity_task_queue(namespace: namespace, task_queue: task_queue)
62
+ rescue StandardError => error
63
+ Temporal.logger.error("Unable to poll activity task queue: #{error.inspect}")
64
+ nil
65
+ end
66
+
67
+ def process(task)
68
+ client = Temporal::Client.generate
69
+ middleware_chain = Middleware::Chain.new(middleware)
70
+
71
+ TaskProcessor.new(task, namespace, activity_lookup, client, middleware_chain).process
72
+ end
73
+
74
+ def thread_pool
75
+ @thread_pool ||= ThreadPool.new(THREAD_POOL_SIZE)
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,78 @@
1
+ require 'temporal/metadata'
2
+ require 'temporal/errors'
3
+ require 'temporal/activity/context'
4
+ require 'temporal/json'
5
+
6
+ module Temporal
7
+ class Activity
8
+ class TaskProcessor
9
+ def initialize(task, namespace, activity_lookup, client, middleware_chain)
10
+ @task = task
11
+ @namespace = namespace
12
+ @task_token = task.task_token
13
+ @activity_name = task.activity_type.name
14
+ @activity_class = activity_lookup.find(activity_name)
15
+ @client = client
16
+ @middleware_chain = middleware_chain
17
+ end
18
+
19
+ def process
20
+ start_time = Time.now
21
+
22
+ Temporal.logger.info("Processing activity task for #{activity_name}")
23
+ Temporal.metrics.timing('activity_task.queue_time', queue_time_ms, activity: activity_name)
24
+
25
+ if !activity_class
26
+ raise ActivityNotRegistered, 'Activity is not registered with this worker'
27
+ end
28
+
29
+ metadata = Metadata.generate(Metadata::ACTIVITY_TYPE, task, namespace)
30
+ context = Activity::Context.new(client, metadata)
31
+
32
+ result = middleware_chain.invoke(metadata) do
33
+ activity_class.execute_in_context(context, parse_payload(task.input))
34
+ end
35
+
36
+ # Do not complete asynchronous activities, these should be completed manually
37
+ respond_completed(result) unless context.async?
38
+ rescue StandardError, ScriptError => error
39
+ respond_failed(error)
40
+ ensure
41
+ time_diff_ms = ((Time.now - start_time) * 1000).round
42
+ Temporal.metrics.timing('activity_task.latency', time_diff_ms, activity: activity_name)
43
+ Temporal.logger.debug("Activity task processed in #{time_diff_ms}ms")
44
+ end
45
+
46
+ private
47
+
48
+ attr_reader :task, :namespace, :task_token, :activity_name, :activity_class, :client, :middleware_chain
49
+
50
+ def queue_time_ms
51
+ scheduled = task.current_attempt_scheduled_time.to_f
52
+ started = task.started_time.to_f
53
+ ((started - scheduled) * 1_000).round
54
+ end
55
+
56
+ def respond_completed(result)
57
+ Temporal.logger.info("Activity #{activity_name} completed")
58
+ client.respond_activity_task_completed(task_token: task_token, result: result)
59
+ rescue StandardError => error
60
+ Temporal.logger.error("Unable to complete Activity #{activity_name}: #{error.inspect}")
61
+ end
62
+
63
+ def respond_failed(error)
64
+ Temporal.logger.error("Activity #{activity_name} failed with: #{error.inspect}")
65
+ client.respond_activity_task_failed(task_token: task_token, exception: error)
66
+ rescue StandardError => error
67
+ Temporal.logger.error("Unable to fail Activity #{activity_name}: #{error.inspect}")
68
+ end
69
+
70
+ def parse_payload(payload)
71
+ return if payload.nil? || payload.payloads.empty?
72
+
73
+ binary = payload.payloads.first.data
74
+ JSON.deserialize(binary)
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,41 @@
1
+ # This module provides a set of methods for imitating direct Activities calls
2
+ # from within Workflows:
3
+ #
4
+ # class TestWorkflow < Temporal::Workflow
5
+ # def execute
6
+ # TestActivity.execute!('foo', 'bar')
7
+ # end
8
+ # end
9
+ #
10
+ # This is analogous to calling:
11
+ #
12
+ # workflow.execute_activity(TestActivity, 'foo', 'bar')
13
+ #
14
+ require 'temporal/thread_local_context'
15
+
16
+ module Temporal
17
+ class Activity
18
+ module WorkflowConvenienceMethods
19
+ def execute(*input, **args)
20
+ context = Temporal::ThreadLocalContext.get
21
+ raise 'Called Activity#execute outside of a Workflow context' unless context
22
+
23
+ context.execute_activity(self, *input, **args)
24
+ end
25
+
26
+ def execute!(*input, **args)
27
+ context = Temporal::ThreadLocalContext.get
28
+ raise 'Called Activity#execute! outside of a Workflow context' unless context
29
+
30
+ context.execute_activity!(self, *input, **args)
31
+ end
32
+
33
+ def execute_locally(*input, **args)
34
+ context = Temporal::ThreadLocalContext.get
35
+ raise 'Called Activity#execute_locally outside of a Workflow context' unless context
36
+
37
+ context.execute_local_activity(self, *input, **args)
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,21 @@
1
+ require 'temporal/client/grpc_client'
2
+
3
+ module Temporal
4
+ module Client
5
+ CLIENT_TYPES_MAP = {
6
+ grpc: Temporal::Client::GRPCClient
7
+ }.freeze
8
+
9
+ def self.generate
10
+ client_class = CLIENT_TYPES_MAP[Temporal.configuration.client_type]
11
+ host = Temporal.configuration.host
12
+ port = Temporal.configuration.port
13
+
14
+ hostname = `hostname`
15
+ thread_id = Thread.current.object_id
16
+ identity = "#{thread_id}@#{hostname}"
17
+
18
+ client_class.new(host, port, identity)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,8 @@
1
+ module Temporal
2
+ module Client
3
+ class Error < StandardError; end
4
+
5
+ # incorrect arguments passed to the client
6
+ class ArgumentError < Error; end
7
+ end
8
+ end
@@ -0,0 +1,345 @@
1
+ require 'grpc'
2
+ require 'google/protobuf/well_known_types'
3
+ require 'securerandom'
4
+ require 'temporal/json'
5
+ require 'temporal/client/errors'
6
+ require 'temporal/client/serializer'
7
+ require 'temporal/client/serializer/payload'
8
+ require 'temporal/client/serializer/failure'
9
+ require 'gen/temporal/api/workflowservice/v1/service_services_pb'
10
+
11
+ module Temporal
12
+ module Client
13
+ class GRPCClient
14
+ WORKFLOW_ID_REUSE_POLICY = {
15
+ allow_failed: Temporal::Api::Enums::V1::WorkflowIdReusePolicy::WORKFLOW_ID_REUSE_POLICY_ALLOW_DUPLICATE_FAILED_ONLY,
16
+ allow: Temporal::Api::Enums::V1::WorkflowIdReusePolicy::WORKFLOW_ID_REUSE_POLICY_ALLOW_DUPLICATE,
17
+ reject: Temporal::Api::Enums::V1::WorkflowIdReusePolicy::WORKFLOW_ID_REUSE_POLICY_REJECT_DUPLICATE
18
+ }.freeze
19
+
20
+ def initialize(host, port, identity)
21
+ @url = "#{host}:#{port}"
22
+ @identity = identity
23
+ end
24
+
25
+ def register_namespace(name:, description: nil, global: false, retention_period: 10)
26
+ request = Temporal::Api::WorkflowService::V1::RegisterNamespaceRequest.new(
27
+ name: name,
28
+ description: description,
29
+ is_global_namespace: global,
30
+ workflow_execution_retention_period: Google::Protobuf::Duration.new(
31
+ seconds: retention_period * 24 * 60 * 60
32
+ )
33
+ )
34
+ client.register_namespace(request)
35
+ rescue GRPC::AlreadyExists => e
36
+ raise Temporal::NamespaceAlreadyExistsFailure, e.details
37
+ end
38
+
39
+ def describe_namespace(name:)
40
+ request = Temporal::Api::WorkflowService::V1::DescribeNamespaceRequest.new(name: name)
41
+ client.describe_namespace(request)
42
+ end
43
+
44
+ def list_namespaces(page_size:)
45
+ request = Temporal::Api::WorkflowService::V1::ListNamespacesRequest.new(pageSize: page_size)
46
+ client.list_namespaces(request)
47
+ end
48
+
49
+ def update_namespace(name:, description:)
50
+ request = Temporal::Api::WorkflowService::V1::UpdateNamespaceRequest.new(
51
+ name: name,
52
+ update_info: Temporal::Api::WorkflowService::V1::UpdateNamespaceInfo.new(
53
+ description: description
54
+ )
55
+ )
56
+ client.update_namespace(request)
57
+ end
58
+
59
+ def deprecate_namespace(name:)
60
+ request = Temporal::Api::WorkflowService::V1::DeprecateNamespaceRequest.new(name: name)
61
+ client.deprecate_namespace(request)
62
+ end
63
+
64
+ def start_workflow_execution(
65
+ namespace:,
66
+ workflow_id:,
67
+ workflow_name:,
68
+ task_queue:,
69
+ input: nil,
70
+ execution_timeout:,
71
+ task_timeout:,
72
+ workflow_id_reuse_policy: nil,
73
+ headers: nil
74
+ )
75
+ request = Temporal::Api::WorkflowService::V1::StartWorkflowExecutionRequest.new(
76
+ identity: identity,
77
+ namespace: namespace,
78
+ workflow_type: Temporal::Api::Common::V1::WorkflowType.new(
79
+ name: workflow_name
80
+ ),
81
+ workflow_id: workflow_id,
82
+ task_queue: Temporal::Api::TaskQueue::V1::TaskQueue.new(
83
+ name: task_queue
84
+ ),
85
+ input: Serializer::Payload.new(input).to_proto,
86
+ workflow_execution_timeout: execution_timeout,
87
+ workflow_run_timeout: execution_timeout,
88
+ workflow_task_timeout: task_timeout,
89
+ request_id: SecureRandom.uuid,
90
+ header: Temporal::Api::Common::V1::Header.new(
91
+ fields: headers
92
+ )
93
+ )
94
+
95
+ if workflow_id_reuse_policy
96
+ policy = WORKFLOW_ID_REUSE_POLICY[workflow_id_reuse_policy]
97
+ raise Client::ArgumentError, 'Unknown workflow_id_reuse_policy specified' unless policy
98
+
99
+ request.workflow_id_reuse_policy = policy
100
+ end
101
+
102
+ client.start_workflow_execution(request)
103
+ rescue GRPC::AlreadyExists => e
104
+ # Feel like there should be cleaner way to do this...
105
+ run_id = e.details[/RunId: (.*)\.$/, 1]
106
+ raise Temporal::WorkflowExecutionAlreadyStartedFailure.new(e.details, run_id)
107
+ end
108
+
109
+ def get_workflow_execution_history(namespace:, workflow_id:, run_id:)
110
+ request = Temporal::Api::WorkflowService::V1::GetWorkflowExecutionHistoryRequest.new(
111
+ namespace: namespace,
112
+ execution: Temporal::Api::Common::V1::WorkflowExecution.new(
113
+ workflow_id: workflow_id,
114
+ run_id: run_id
115
+ )
116
+ )
117
+
118
+ client.get_workflow_execution_history(request)
119
+ end
120
+
121
+ def poll_workflow_task_queue(namespace:, task_queue:)
122
+ request = Temporal::Api::WorkflowService::V1::PollWorkflowTaskQueueRequest.new(
123
+ identity: identity,
124
+ namespace: namespace,
125
+ task_queue: Temporal::Api::TaskQueue::V1::TaskQueue.new(
126
+ name: task_queue
127
+ )
128
+ )
129
+ client.poll_workflow_task_queue(request)
130
+ end
131
+
132
+ def respond_workflow_task_completed(task_token:, commands:)
133
+ request = Temporal::Api::WorkflowService::V1::RespondWorkflowTaskCompletedRequest.new(
134
+ identity: identity,
135
+ task_token: task_token,
136
+ commands: Array(commands).map { |(_, command)| Serializer.serialize(command) }
137
+ )
138
+ client.respond_workflow_task_completed(request)
139
+ end
140
+
141
+ def respond_workflow_task_failed(task_token:, cause:, exception: nil)
142
+ request = Temporal::Api::WorkflowService::V1::RespondWorkflowTaskFailedRequest.new(
143
+ identity: identity,
144
+ task_token: task_token,
145
+ cause: cause,
146
+ failure: Serializer::Failure.new(exception).to_proto
147
+ )
148
+ client.respond_workflow_task_failed(request)
149
+ end
150
+
151
+ def poll_activity_task_queue(namespace:, task_queue:)
152
+ request = Temporal::Api::WorkflowService::V1::PollActivityTaskQueueRequest.new(
153
+ identity: identity,
154
+ namespace: namespace,
155
+ task_queue: Temporal::Api::TaskQueue::V1::TaskQueue.new(
156
+ name: task_queue
157
+ )
158
+ )
159
+ client.poll_activity_task_queue(request)
160
+ end
161
+
162
+ def record_activity_task_heartbeat(task_token:, details: nil)
163
+ request = Temporal::Api::WorkflowService::V1::RecordActivityTaskHeartbeatRequest.new(
164
+ task_token: task_token,
165
+ details: Serializer::Payload.new(details).to_proto,
166
+ identity: identity
167
+ )
168
+ client.record_activity_task_heartbeat(request)
169
+ end
170
+
171
+ def record_activity_task_heartbeat_by_id
172
+ raise NotImplementedError
173
+ end
174
+
175
+ def respond_activity_task_completed(task_token:, result:)
176
+ request = Temporal::Api::WorkflowService::V1::RespondActivityTaskCompletedRequest.new(
177
+ identity: identity,
178
+ task_token: task_token,
179
+ result: Serializer::Payload.new(result).to_proto,
180
+ )
181
+ client.respond_activity_task_completed(request)
182
+ end
183
+
184
+ def respond_activity_task_completed_by_id(namespace:, activity_id:, workflow_id:, run_id:, result:)
185
+ request = Temporal::Api::WorkflowService::V1::RespondActivityTaskCompletedByIdRequest.new(
186
+ identity: identity,
187
+ namespace: namespace,
188
+ workflow_id: workflow_id,
189
+ run_id: run_id,
190
+ activity_id: activity_id,
191
+ result: Serializer::Payload.new(result).to_proto
192
+ )
193
+ client.respond_activity_task_completed_by_id(request)
194
+ end
195
+
196
+ def respond_activity_task_failed(task_token:, exception:)
197
+ request = Temporal::Api::WorkflowService::V1::RespondActivityTaskFailedRequest.new(
198
+ identity: identity,
199
+ task_token: task_token,
200
+ failure: Serializer::Failure.new(exception).to_proto
201
+ )
202
+ client.respond_activity_task_failed(request)
203
+ end
204
+
205
+ def respond_activity_task_failed_by_id(namespace:, activity_id:, workflow_id:, run_id:, exception:)
206
+ request = Temporal::Api::WorkflowService::V1::RespondActivityTaskFailedByIdRequest.new(
207
+ identity: identity,
208
+ namespace: namespace,
209
+ workflow_id: workflow_id,
210
+ run_id: run_id,
211
+ activity_id: activity_id,
212
+ failure: Serializer::Failure.new(exception).to_proto
213
+ )
214
+ client.respond_activity_task_failed_by_id(request)
215
+ end
216
+
217
+ def respond_activity_task_canceled(task_token:, details: nil)
218
+ request = Temporal::Api::WorkflowService::V1::RespondActivityTaskCanceledRequest.new(
219
+ task_token: task_token,
220
+ details: Serializer::Payload.new(details).to_proto,
221
+ identity: identity
222
+ )
223
+ client.respond_activity_task_canceled(request)
224
+ end
225
+
226
+ def respond_activity_task_canceled_by_id
227
+ raise NotImplementedError
228
+ end
229
+
230
+ def request_cancel_workflow_execution
231
+ raise NotImplementedError
232
+ end
233
+
234
+ def signal_workflow_execution(namespace:, workflow_id:, run_id:, signal:, input: nil)
235
+ request = Temporal::Api::WorkflowService::V1::SignalWorkflowExecutionRequest.new(
236
+ namespace: namespace,
237
+ workflow_execution: Temporal::Api::Common::V1::WorkflowExecution.new(
238
+ workflow_id: workflow_id,
239
+ run_id: run_id
240
+ ),
241
+ signal_name: signal,
242
+ input: Serializer::Payload.new(input).to_proto,
243
+ identity: identity
244
+ )
245
+ client.signal_workflow_execution(request)
246
+ end
247
+
248
+ def signal_with_start_workflow_execution
249
+ raise NotImplementedError
250
+ end
251
+
252
+ def reset_workflow_execution(namespace:, workflow_id:, run_id:, reason:, workflow_task_event_id:)
253
+ request = Temporal::Api::WorkflowService::V1::ResetWorkflowExecutionRequest.new(
254
+ namespace: namespace,
255
+ workflow_execution: Temporal::Api::Common::V1::WorkflowExecution.new(
256
+ workflow_id: workflow_id,
257
+ run_id: run_id
258
+ ),
259
+ reason: reason,
260
+ workflow_task_finish_event_id: workflow_task_event_id
261
+ )
262
+ client.reset_workflow_execution(request)
263
+ end
264
+
265
+ def terminate_workflow_execution
266
+ raise NotImplementedError
267
+ end
268
+
269
+ def list_open_workflow_executions
270
+ raise NotImplementedError
271
+ end
272
+
273
+ def list_closed_workflow_executions
274
+ raise NotImplementedError
275
+ end
276
+
277
+ def list_workflow_executions
278
+ raise NotImplementedError
279
+ end
280
+
281
+ def list_archived_workflow_executions
282
+ raise NotImplementedError
283
+ end
284
+
285
+ def scan_workflow_executions
286
+ raise NotImplementedError
287
+ end
288
+
289
+ def count_workflow_executions
290
+ raise NotImplementedError
291
+ end
292
+
293
+ def get_search_attributes
294
+ raise NotImplementedError
295
+ end
296
+
297
+ def respond_query_task_completed
298
+ raise NotImplementedError
299
+ end
300
+
301
+ def reset_sticky_task_queue
302
+ raise NotImplementedError
303
+ end
304
+
305
+ def query_workflow
306
+ raise NotImplementedError
307
+ end
308
+
309
+ def describe_workflow_execution(namespace:, workflow_id:, run_id:)
310
+ request = Temporal::Api::WorkflowService::V1::DescribeWorkflowExecutionRequest.new(
311
+ namespace: namespace,
312
+ execution: Temporal::Api::Common::V1::WorkflowExecution.new(
313
+ workflow_id: workflow_id,
314
+ run_id: run_id
315
+ )
316
+ )
317
+ client.describe_workflow_execution(request)
318
+ end
319
+
320
+ def describe_task_queue(namespace:, task_queue:)
321
+ request = Temporal::Api::WorkflowService::V1::DescribeTaskQueueRequest.new(
322
+ namespace: namespace,
323
+ task_queue: Temporal::Api::TaskQueue::V1::TaskQueue.new(
324
+ name: task_queue
325
+ ),
326
+ task_queue_type: Temporal::Api::Enums::V1::TaskQueueType::Workflow,
327
+ include_task_queue_status: true
328
+ )
329
+ client.describe_task_queue(request)
330
+ end
331
+
332
+ private
333
+
334
+ attr_reader :url, :identity
335
+
336
+ def client
337
+ @client ||= Temporal::Api::WorkflowService::V1::WorkflowService::Stub.new(
338
+ url,
339
+ :this_channel_is_insecure,
340
+ timeout: 5
341
+ )
342
+ end
343
+ end
344
+ end
345
+ end