temporal-ruby 0.0.0 → 0.0.1.pre.pre1

Sign up to get free protection for your applications and to get access to all the features.
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