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.
- checksums.yaml +4 -4
- data/README.md +19 -42
- data/lib/gen/temporal/api/command/v1/message_pb.rb +146 -0
- data/lib/gen/temporal/api/common/v1/message_pb.rb +67 -0
- data/lib/gen/temporal/api/enums/v1/command_type_pb.rb +35 -0
- data/lib/gen/temporal/api/enums/v1/common_pb.rb +34 -0
- data/lib/gen/temporal/api/enums/v1/event_type_pb.rb +62 -0
- data/lib/gen/temporal/api/enums/v1/failed_cause_pb.rb +60 -0
- data/lib/gen/temporal/api/enums/v1/namespace_pb.rb +31 -0
- data/lib/gen/temporal/api/enums/v1/query_pb.rb +31 -0
- data/lib/gen/temporal/api/enums/v1/task_queue_pb.rb +30 -0
- data/lib/gen/temporal/api/enums/v1/workflow_pb.rb +82 -0
- data/lib/gen/temporal/api/errordetails/v1/message_pb.rb +55 -0
- data/lib/gen/temporal/api/failure/v1/message_pb.rb +81 -0
- data/lib/gen/temporal/api/filter/v1/message_pb.rb +38 -0
- data/lib/gen/temporal/api/history/v1/message_pb.rb +423 -0
- data/lib/gen/temporal/api/namespace/v1/message_pb.rb +55 -0
- data/lib/gen/temporal/api/query/v1/message_pb.rb +36 -0
- data/lib/gen/temporal/api/replication/v1/message_pb.rb +27 -0
- data/lib/gen/temporal/api/taskqueue/v1/message_pb.rb +60 -0
- data/lib/gen/temporal/api/version/v1/message_pb.rb +28 -0
- data/lib/gen/temporal/api/workflow/v1/message_pb.rb +83 -0
- data/lib/gen/temporal/api/workflowservice/v1/request_response_pb.rb +538 -0
- data/lib/gen/temporal/api/workflowservice/v1/service_pb.rb +19 -0
- data/lib/gen/temporal/api/workflowservice/v1/service_services_pb.rb +223 -0
- data/lib/temporal-ruby.rb +1 -0
- data/lib/temporal.rb +137 -0
- data/lib/temporal/activity.rb +33 -0
- data/lib/temporal/activity/async_token.rb +34 -0
- data/lib/temporal/activity/context.rb +64 -0
- data/lib/temporal/activity/poller.rb +79 -0
- data/lib/temporal/activity/task_processor.rb +78 -0
- data/lib/temporal/activity/workflow_convenience_methods.rb +41 -0
- data/lib/temporal/client.rb +21 -0
- data/lib/temporal/client/errors.rb +8 -0
- data/lib/temporal/client/grpc_client.rb +345 -0
- data/lib/temporal/client/serializer.rb +31 -0
- data/lib/temporal/client/serializer/base.rb +23 -0
- data/lib/temporal/client/serializer/cancel_timer.rb +19 -0
- data/lib/temporal/client/serializer/complete_workflow.rb +20 -0
- data/lib/temporal/client/serializer/fail_workflow.rb +20 -0
- data/lib/temporal/client/serializer/failure.rb +29 -0
- data/lib/temporal/client/serializer/payload.rb +25 -0
- data/lib/temporal/client/serializer/record_marker.rb +23 -0
- data/lib/temporal/client/serializer/request_activity_cancellation.rb +19 -0
- data/lib/temporal/client/serializer/schedule_activity.rb +53 -0
- data/lib/temporal/client/serializer/start_child_workflow.rb +51 -0
- data/lib/temporal/client/serializer/start_timer.rb +20 -0
- data/lib/temporal/concerns/executable.rb +37 -0
- data/lib/temporal/concerns/typed.rb +40 -0
- data/lib/temporal/configuration.rb +44 -0
- data/lib/temporal/errors.rb +38 -0
- data/lib/temporal/executable_lookup.rb +25 -0
- data/lib/temporal/execution_options.rb +35 -0
- data/lib/temporal/json.rb +18 -0
- data/lib/temporal/metadata.rb +68 -0
- data/lib/temporal/metadata/activity.rb +27 -0
- data/lib/temporal/metadata/base.rb +17 -0
- data/lib/temporal/metadata/workflow.rb +22 -0
- data/lib/temporal/metadata/workflow_task.rb +25 -0
- data/lib/temporal/metrics.rb +37 -0
- data/lib/temporal/metrics_adapters/log.rb +33 -0
- data/lib/temporal/metrics_adapters/null.rb +9 -0
- data/lib/temporal/middleware/chain.rb +30 -0
- data/lib/temporal/middleware/entry.rb +9 -0
- data/lib/temporal/retry_policy.rb +27 -0
- data/lib/temporal/saga/concern.rb +23 -0
- data/lib/temporal/saga/result.rb +22 -0
- data/lib/temporal/saga/saga.rb +24 -0
- data/lib/temporal/testing.rb +50 -0
- data/lib/temporal/testing/future_registry.rb +27 -0
- data/lib/temporal/testing/local_activity_context.rb +17 -0
- data/lib/temporal/testing/local_workflow_context.rb +178 -0
- data/lib/temporal/testing/temporal_override.rb +121 -0
- data/lib/temporal/testing/workflow_execution.rb +44 -0
- data/lib/temporal/testing/workflow_override.rb +36 -0
- data/lib/temporal/thread_local_context.rb +14 -0
- data/lib/temporal/thread_pool.rb +63 -0
- data/lib/temporal/types.rb +7 -0
- data/lib/temporal/uuid.rb +19 -0
- data/lib/temporal/version.rb +1 -1
- data/lib/temporal/worker.rb +88 -0
- data/lib/temporal/workflow.rb +42 -0
- data/lib/temporal/workflow/command.rb +39 -0
- data/lib/temporal/workflow/command_state_machine.rb +48 -0
- data/lib/temporal/workflow/context.rb +243 -0
- data/lib/temporal/workflow/convenience_methods.rb +34 -0
- data/lib/temporal/workflow/dispatcher.rb +31 -0
- data/lib/temporal/workflow/execution_info.rb +51 -0
- data/lib/temporal/workflow/executor.rb +45 -0
- data/lib/temporal/workflow/future.rb +77 -0
- data/lib/temporal/workflow/history.rb +76 -0
- data/lib/temporal/workflow/history/event.rb +69 -0
- data/lib/temporal/workflow/history/event_target.rb +75 -0
- data/lib/temporal/workflow/history/window.rb +40 -0
- data/lib/temporal/workflow/poller.rb +67 -0
- data/lib/temporal/workflow/replay_aware_logger.rb +36 -0
- data/lib/temporal/workflow/state_manager.rb +342 -0
- data/lib/temporal/workflow/task_processor.rb +78 -0
- data/rbi/temporal-ruby.rbi +43 -0
- data/temporal.gemspec +10 -2
- 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,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
|