amit-temporalio 0.3.0-aarch64-linux-musl
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 +7 -0
- data/.yardopts +2 -0
- data/Gemfile +23 -0
- data/Rakefile +101 -0
- data/lib/temporalio/activity/complete_async_error.rb +11 -0
- data/lib/temporalio/activity/context.rb +116 -0
- data/lib/temporalio/activity/definition.rb +189 -0
- data/lib/temporalio/activity/info.rb +64 -0
- data/lib/temporalio/activity.rb +12 -0
- data/lib/temporalio/api/activity/v1/message.rb +25 -0
- data/lib/temporalio/api/batch/v1/message.rb +31 -0
- data/lib/temporalio/api/cloud/account/v1/message.rb +28 -0
- data/lib/temporalio/api/cloud/cloudservice/v1/request_response.rb +126 -0
- data/lib/temporalio/api/cloud/cloudservice/v1/service.rb +25 -0
- data/lib/temporalio/api/cloud/cloudservice.rb +3 -0
- data/lib/temporalio/api/cloud/identity/v1/message.rb +41 -0
- data/lib/temporalio/api/cloud/namespace/v1/message.rb +42 -0
- data/lib/temporalio/api/cloud/nexus/v1/message.rb +31 -0
- data/lib/temporalio/api/cloud/operation/v1/message.rb +28 -0
- data/lib/temporalio/api/cloud/region/v1/message.rb +24 -0
- data/lib/temporalio/api/cloud/resource/v1/message.rb +23 -0
- data/lib/temporalio/api/cloud/sink/v1/message.rb +24 -0
- data/lib/temporalio/api/cloud/usage/v1/message.rb +31 -0
- data/lib/temporalio/api/command/v1/message.rb +46 -0
- data/lib/temporalio/api/common/v1/grpc_status.rb +23 -0
- data/lib/temporalio/api/common/v1/message.rb +47 -0
- data/lib/temporalio/api/enums/v1/batch_operation.rb +22 -0
- data/lib/temporalio/api/enums/v1/command_type.rb +21 -0
- data/lib/temporalio/api/enums/v1/common.rb +26 -0
- data/lib/temporalio/api/enums/v1/event_type.rb +21 -0
- data/lib/temporalio/api/enums/v1/failed_cause.rb +26 -0
- data/lib/temporalio/api/enums/v1/namespace.rb +23 -0
- data/lib/temporalio/api/enums/v1/query.rb +22 -0
- data/lib/temporalio/api/enums/v1/reset.rb +23 -0
- data/lib/temporalio/api/enums/v1/schedule.rb +21 -0
- data/lib/temporalio/api/enums/v1/task_queue.rb +25 -0
- data/lib/temporalio/api/enums/v1/update.rb +22 -0
- data/lib/temporalio/api/enums/v1/workflow.rb +30 -0
- data/lib/temporalio/api/errordetails/v1/message.rb +42 -0
- data/lib/temporalio/api/export/v1/message.rb +24 -0
- data/lib/temporalio/api/failure/v1/message.rb +35 -0
- data/lib/temporalio/api/filter/v1/message.rb +27 -0
- data/lib/temporalio/api/history/v1/message.rb +90 -0
- data/lib/temporalio/api/namespace/v1/message.rb +31 -0
- data/lib/temporalio/api/nexus/v1/message.rb +40 -0
- data/lib/temporalio/api/operatorservice/v1/request_response.rb +49 -0
- data/lib/temporalio/api/operatorservice/v1/service.rb +23 -0
- data/lib/temporalio/api/operatorservice.rb +3 -0
- data/lib/temporalio/api/payload_visitor.rb +1513 -0
- data/lib/temporalio/api/protocol/v1/message.rb +23 -0
- data/lib/temporalio/api/query/v1/message.rb +27 -0
- data/lib/temporalio/api/replication/v1/message.rb +26 -0
- data/lib/temporalio/api/schedule/v1/message.rb +43 -0
- data/lib/temporalio/api/sdk/v1/enhanced_stack_trace.rb +25 -0
- data/lib/temporalio/api/sdk/v1/task_complete_metadata.rb +21 -0
- data/lib/temporalio/api/sdk/v1/user_metadata.rb +23 -0
- data/lib/temporalio/api/sdk/v1/workflow_metadata.rb +23 -0
- data/lib/temporalio/api/taskqueue/v1/message.rb +45 -0
- data/lib/temporalio/api/testservice/v1/request_response.rb +31 -0
- data/lib/temporalio/api/testservice/v1/service.rb +23 -0
- data/lib/temporalio/api/update/v1/message.rb +33 -0
- data/lib/temporalio/api/version/v1/message.rb +26 -0
- data/lib/temporalio/api/workflow/v1/message.rb +43 -0
- data/lib/temporalio/api/workflowservice/v1/request_response.rb +204 -0
- data/lib/temporalio/api/workflowservice/v1/service.rb +23 -0
- data/lib/temporalio/api/workflowservice.rb +3 -0
- data/lib/temporalio/api.rb +14 -0
- data/lib/temporalio/cancellation.rb +170 -0
- data/lib/temporalio/client/activity_id_reference.rb +32 -0
- data/lib/temporalio/client/async_activity_handle.rb +85 -0
- data/lib/temporalio/client/connection/cloud_service.rb +726 -0
- data/lib/temporalio/client/connection/operator_service.rb +201 -0
- data/lib/temporalio/client/connection/service.rb +42 -0
- data/lib/temporalio/client/connection/test_service.rb +111 -0
- data/lib/temporalio/client/connection/workflow_service.rb +1041 -0
- data/lib/temporalio/client/connection.rb +316 -0
- data/lib/temporalio/client/interceptor.rb +416 -0
- data/lib/temporalio/client/schedule.rb +967 -0
- data/lib/temporalio/client/schedule_handle.rb +126 -0
- data/lib/temporalio/client/workflow_execution.rb +100 -0
- data/lib/temporalio/client/workflow_execution_count.rb +36 -0
- data/lib/temporalio/client/workflow_execution_status.rb +18 -0
- data/lib/temporalio/client/workflow_handle.rb +389 -0
- data/lib/temporalio/client/workflow_query_reject_condition.rb +14 -0
- data/lib/temporalio/client/workflow_update_handle.rb +65 -0
- data/lib/temporalio/client/workflow_update_wait_stage.rb +17 -0
- data/lib/temporalio/client.rb +484 -0
- data/lib/temporalio/common_enums.rb +41 -0
- data/lib/temporalio/converters/data_converter.rb +99 -0
- data/lib/temporalio/converters/failure_converter.rb +202 -0
- data/lib/temporalio/converters/payload_codec.rb +26 -0
- data/lib/temporalio/converters/payload_converter/binary_null.rb +34 -0
- data/lib/temporalio/converters/payload_converter/binary_plain.rb +35 -0
- data/lib/temporalio/converters/payload_converter/binary_protobuf.rb +42 -0
- data/lib/temporalio/converters/payload_converter/composite.rb +66 -0
- data/lib/temporalio/converters/payload_converter/encoding.rb +35 -0
- data/lib/temporalio/converters/payload_converter/json_plain.rb +44 -0
- data/lib/temporalio/converters/payload_converter/json_protobuf.rb +41 -0
- data/lib/temporalio/converters/payload_converter.rb +71 -0
- data/lib/temporalio/converters/raw_value.rb +20 -0
- data/lib/temporalio/converters.rb +9 -0
- data/lib/temporalio/error/failure.rb +219 -0
- data/lib/temporalio/error.rb +155 -0
- data/lib/temporalio/internal/bridge/api/activity_result/activity_result.rb +34 -0
- data/lib/temporalio/internal/bridge/api/activity_task/activity_task.rb +31 -0
- data/lib/temporalio/internal/bridge/api/child_workflow/child_workflow.rb +33 -0
- data/lib/temporalio/internal/bridge/api/common/common.rb +26 -0
- data/lib/temporalio/internal/bridge/api/core_interface.rb +40 -0
- data/lib/temporalio/internal/bridge/api/external_data/external_data.rb +27 -0
- data/lib/temporalio/internal/bridge/api/nexus/nexus.rb +33 -0
- data/lib/temporalio/internal/bridge/api/workflow_activation/workflow_activation.rb +56 -0
- data/lib/temporalio/internal/bridge/api/workflow_commands/workflow_commands.rb +57 -0
- data/lib/temporalio/internal/bridge/api/workflow_completion/workflow_completion.rb +30 -0
- data/lib/temporalio/internal/bridge/api.rb +3 -0
- data/lib/temporalio/internal/bridge/client.rb +95 -0
- data/lib/temporalio/internal/bridge/runtime.rb +53 -0
- data/lib/temporalio/internal/bridge/temporalio_bridge.so +0 -0
- data/lib/temporalio/internal/bridge/testing.rb +66 -0
- data/lib/temporalio/internal/bridge/worker.rb +85 -0
- data/lib/temporalio/internal/bridge.rb +36 -0
- data/lib/temporalio/internal/client/implementation.rb +700 -0
- data/lib/temporalio/internal/metric.rb +122 -0
- data/lib/temporalio/internal/proto_utils.rb +133 -0
- data/lib/temporalio/internal/worker/activity_worker.rb +376 -0
- data/lib/temporalio/internal/worker/multi_runner.rb +213 -0
- data/lib/temporalio/internal/worker/workflow_instance/child_workflow_handle.rb +54 -0
- data/lib/temporalio/internal/worker/workflow_instance/context.rb +333 -0
- data/lib/temporalio/internal/worker/workflow_instance/details.rb +44 -0
- data/lib/temporalio/internal/worker/workflow_instance/external_workflow_handle.rb +32 -0
- data/lib/temporalio/internal/worker/workflow_instance/externally_immutable_hash.rb +22 -0
- data/lib/temporalio/internal/worker/workflow_instance/handler_execution.rb +25 -0
- data/lib/temporalio/internal/worker/workflow_instance/handler_hash.rb +41 -0
- data/lib/temporalio/internal/worker/workflow_instance/illegal_call_tracer.rb +97 -0
- data/lib/temporalio/internal/worker/workflow_instance/inbound_implementation.rb +62 -0
- data/lib/temporalio/internal/worker/workflow_instance/outbound_implementation.rb +415 -0
- data/lib/temporalio/internal/worker/workflow_instance/replay_safe_logger.rb +37 -0
- data/lib/temporalio/internal/worker/workflow_instance/replay_safe_metric.rb +40 -0
- data/lib/temporalio/internal/worker/workflow_instance/scheduler.rb +163 -0
- data/lib/temporalio/internal/worker/workflow_instance.rb +730 -0
- data/lib/temporalio/internal/worker/workflow_worker.rb +236 -0
- data/lib/temporalio/internal.rb +7 -0
- data/lib/temporalio/metric.rb +109 -0
- data/lib/temporalio/retry_policy.rb +74 -0
- data/lib/temporalio/runtime.rb +314 -0
- data/lib/temporalio/scoped_logger.rb +96 -0
- data/lib/temporalio/search_attributes.rb +343 -0
- data/lib/temporalio/testing/activity_environment.rb +136 -0
- data/lib/temporalio/testing/workflow_environment.rb +383 -0
- data/lib/temporalio/testing.rb +10 -0
- data/lib/temporalio/version.rb +5 -0
- data/lib/temporalio/worker/activity_executor/fiber.rb +49 -0
- data/lib/temporalio/worker/activity_executor/thread_pool.rb +46 -0
- data/lib/temporalio/worker/activity_executor.rb +55 -0
- data/lib/temporalio/worker/interceptor.rb +362 -0
- data/lib/temporalio/worker/thread_pool.rb +237 -0
- data/lib/temporalio/worker/tuner.rb +189 -0
- data/lib/temporalio/worker/workflow_executor/thread_pool.rb +230 -0
- data/lib/temporalio/worker/workflow_executor.rb +26 -0
- data/lib/temporalio/worker/workflow_replayer.rb +343 -0
- data/lib/temporalio/worker.rb +569 -0
- data/lib/temporalio/workflow/activity_cancellation_type.rb +20 -0
- data/lib/temporalio/workflow/child_workflow_cancellation_type.rb +21 -0
- data/lib/temporalio/workflow/child_workflow_handle.rb +43 -0
- data/lib/temporalio/workflow/definition.rb +566 -0
- data/lib/temporalio/workflow/external_workflow_handle.rb +41 -0
- data/lib/temporalio/workflow/future.rb +151 -0
- data/lib/temporalio/workflow/handler_unfinished_policy.rb +13 -0
- data/lib/temporalio/workflow/info.rb +82 -0
- data/lib/temporalio/workflow/parent_close_policy.rb +19 -0
- data/lib/temporalio/workflow/update_info.rb +20 -0
- data/lib/temporalio/workflow.rb +529 -0
- data/lib/temporalio/workflow_history.rb +47 -0
- data/lib/temporalio.rb +11 -0
- data/temporalio.gemspec +28 -0
- metadata +236 -0
@@ -0,0 +1,126 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'temporalio/client/interceptor'
|
4
|
+
require 'temporalio/client/schedule'
|
5
|
+
|
6
|
+
module Temporalio
|
7
|
+
class Client
|
8
|
+
# Handle for interacting with a schedule. This is usually created via {Client.create_schedule} or
|
9
|
+
# {Client.schedule_handle}.
|
10
|
+
class ScheduleHandle
|
11
|
+
# @return [String] ID of the schedule.
|
12
|
+
attr_reader :id
|
13
|
+
|
14
|
+
# @!visibility private
|
15
|
+
def initialize(client:, id:)
|
16
|
+
@client = client
|
17
|
+
@id = id
|
18
|
+
end
|
19
|
+
|
20
|
+
# Backfill the schedule by going through the specified time periods as if they passed right now.
|
21
|
+
#
|
22
|
+
# @param backfills [Array<Schedule::Backfill>] Backfill periods.
|
23
|
+
# @param rpc_options [RPCOptions, nil] Advanced RPC options.
|
24
|
+
#
|
25
|
+
# @raise [Error::RPCError] RPC error from call.
|
26
|
+
def backfill(
|
27
|
+
*backfills,
|
28
|
+
rpc_options: nil
|
29
|
+
)
|
30
|
+
raise ArgumentError, 'At least one backfill required' if backfills.empty?
|
31
|
+
|
32
|
+
@client._impl.backfill_schedule(Interceptor::BackfillScheduleInput.new(
|
33
|
+
id:,
|
34
|
+
backfills:,
|
35
|
+
rpc_options:
|
36
|
+
))
|
37
|
+
end
|
38
|
+
|
39
|
+
# Delete this schedule.
|
40
|
+
#
|
41
|
+
# @param rpc_options [RPCOptions, nil] Advanced RPC options.
|
42
|
+
#
|
43
|
+
# @raise [Error::RPCError] RPC error from call.
|
44
|
+
def delete(rpc_options: nil)
|
45
|
+
@client._impl.delete_schedule(Interceptor::DeleteScheduleInput.new(
|
46
|
+
id:,
|
47
|
+
rpc_options:
|
48
|
+
))
|
49
|
+
end
|
50
|
+
|
51
|
+
# Fetch this schedule's description.
|
52
|
+
#
|
53
|
+
# @param rpc_options [RPCOptions, nil] Advanced RPC options.
|
54
|
+
#
|
55
|
+
# @return [Schedule::Description] Schedule description.
|
56
|
+
# @raise [Error::RPCError] RPC error from call.
|
57
|
+
def describe(rpc_options: nil)
|
58
|
+
@client._impl.describe_schedule(Interceptor::DescribeScheduleInput.new(
|
59
|
+
id:,
|
60
|
+
rpc_options:
|
61
|
+
))
|
62
|
+
end
|
63
|
+
|
64
|
+
# Pause the schedule and set a note.
|
65
|
+
#
|
66
|
+
# @param note [String] Note to set on the schedule.
|
67
|
+
# @param rpc_options [RPCOptions, nil] Advanced RPC options.
|
68
|
+
#
|
69
|
+
# @raise [Error::RPCError] RPC error from call.
|
70
|
+
def pause(note: 'Paused via Ruby SDK', rpc_options: nil)
|
71
|
+
@client._impl.pause_schedule(Interceptor::PauseScheduleInput.new(
|
72
|
+
id:,
|
73
|
+
note:,
|
74
|
+
rpc_options:
|
75
|
+
))
|
76
|
+
end
|
77
|
+
|
78
|
+
# Trigger an action on this schedule to happen immediately.
|
79
|
+
#
|
80
|
+
# @param overlap [Schedule::OverlapPolicy, nil] If set, overrides the schedule's overlap policy.
|
81
|
+
# @param rpc_options [RPCOptions, nil] Advanced RPC options.
|
82
|
+
#
|
83
|
+
# @raise [Error::RPCError] RPC error from call.
|
84
|
+
def trigger(overlap: nil, rpc_options: nil)
|
85
|
+
@client._impl.trigger_schedule(Interceptor::TriggerScheduleInput.new(
|
86
|
+
id:,
|
87
|
+
overlap:,
|
88
|
+
rpc_options:
|
89
|
+
))
|
90
|
+
end
|
91
|
+
|
92
|
+
# Unpause the schedule and set a note.
|
93
|
+
#
|
94
|
+
# @param note [String] Note to set on the schedule.
|
95
|
+
# @param rpc_options [RPCOptions, nil] Advanced RPC options.
|
96
|
+
#
|
97
|
+
# @raise [Error::RPCError] RPC error from call.
|
98
|
+
def unpause(note: 'Unpaused via Ruby SDK', rpc_options: nil)
|
99
|
+
@client._impl.unpause_schedule(Interceptor::UnpauseScheduleInput.new(
|
100
|
+
id:,
|
101
|
+
note:,
|
102
|
+
rpc_options:
|
103
|
+
))
|
104
|
+
end
|
105
|
+
|
106
|
+
# Update a schedule using a callback to build the update from the description.
|
107
|
+
#
|
108
|
+
# NOTE: In future versions, the callback may be invoked multiple times in a conflict-resolution loop.
|
109
|
+
#
|
110
|
+
# @param rpc_options [RPCOptions, nil] Advanced RPC options.
|
111
|
+
# @yield Block called to obtain the update.
|
112
|
+
# @yieldparam [Schedule::Update::Input] Parameter to the block that contains a description with the schedule to be
|
113
|
+
# updated.
|
114
|
+
# @yieldreturn [Schedule::Update, nil] The update to apply, or `nil` to not perform an update.
|
115
|
+
#
|
116
|
+
# @raise [Error::RPCError] RPC error from call.
|
117
|
+
def update(rpc_options: nil, &updater)
|
118
|
+
@client._impl.update_schedule(Interceptor::UpdateScheduleInput.new(
|
119
|
+
id:,
|
120
|
+
updater:,
|
121
|
+
rpc_options:
|
122
|
+
))
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'temporalio/api'
|
4
|
+
require 'temporalio/client/workflow_execution_status'
|
5
|
+
require 'temporalio/internal/proto_utils'
|
6
|
+
require 'temporalio/search_attributes'
|
7
|
+
|
8
|
+
module Temporalio
|
9
|
+
class Client
|
10
|
+
# Info for a single workflow execution run.
|
11
|
+
class WorkflowExecution
|
12
|
+
# @return [Api::Workflow::V1::WorkflowExecutionInfo] Underlying protobuf info.
|
13
|
+
attr_reader :raw_info
|
14
|
+
|
15
|
+
# @!visibility private
|
16
|
+
def initialize(raw_info, data_converter)
|
17
|
+
@raw_info = raw_info
|
18
|
+
@memo = Internal::ProtoUtils::LazyMemo.new(raw_info.memo, data_converter)
|
19
|
+
@search_attributes = Internal::ProtoUtils::LazySearchAttributes.new(raw_info.search_attributes)
|
20
|
+
end
|
21
|
+
|
22
|
+
# @return [Time, nil] When the workflow was closed if closed.
|
23
|
+
def close_time
|
24
|
+
Internal::ProtoUtils.timestamp_to_time(@raw_info.close_time)
|
25
|
+
end
|
26
|
+
|
27
|
+
# @return [Time, nil] When this workflow run started or should start.
|
28
|
+
def execution_time
|
29
|
+
Internal::ProtoUtils.timestamp_to_time(@raw_info.execution_time)
|
30
|
+
end
|
31
|
+
|
32
|
+
# @return [Integer] Number of events in the history.
|
33
|
+
def history_length
|
34
|
+
@raw_info.history_length
|
35
|
+
end
|
36
|
+
|
37
|
+
# @return [String] ID for the workflow.
|
38
|
+
def id
|
39
|
+
@raw_info.execution.workflow_id
|
40
|
+
end
|
41
|
+
|
42
|
+
# @return [Hash<String, Object>, nil] Memo for the workflow.
|
43
|
+
def memo
|
44
|
+
@memo.get
|
45
|
+
end
|
46
|
+
|
47
|
+
# @return [String, nil] ID for the parent workflow if this was started as a child.
|
48
|
+
def parent_id
|
49
|
+
@raw_info.parent_execution&.workflow_id
|
50
|
+
end
|
51
|
+
|
52
|
+
# @return [String, nil] Run ID for the parent workflow if this was started as a child.
|
53
|
+
def parent_run_id
|
54
|
+
@raw_info.parent_execution&.run_id
|
55
|
+
end
|
56
|
+
|
57
|
+
# @return [String] Run ID for this workflow run.
|
58
|
+
def run_id
|
59
|
+
@raw_info.execution.run_id
|
60
|
+
end
|
61
|
+
|
62
|
+
# @return [SearchAttributes, nil] Current set of search attributes if any.
|
63
|
+
def search_attributes
|
64
|
+
@search_attributes.get
|
65
|
+
end
|
66
|
+
|
67
|
+
# @return [Time] When the workflow was created.
|
68
|
+
def start_time
|
69
|
+
Internal::ProtoUtils.timestamp_to_time(@raw_info.start_time) || raise # Never nil
|
70
|
+
end
|
71
|
+
|
72
|
+
# @return [WorkflowExecutionStatus] Status for the workflow.
|
73
|
+
def status
|
74
|
+
Internal::ProtoUtils.enum_to_int(Api::Enums::V1::WorkflowExecutionStatus, @raw_info.status)
|
75
|
+
end
|
76
|
+
|
77
|
+
# @return [String] Task queue for the workflow.
|
78
|
+
def task_queue
|
79
|
+
@raw_info.task_queue
|
80
|
+
end
|
81
|
+
|
82
|
+
# @return [String] Type name for the workflow.
|
83
|
+
def workflow_type
|
84
|
+
@raw_info.type.name
|
85
|
+
end
|
86
|
+
|
87
|
+
# Description for a single workflow execution run.
|
88
|
+
class Description < WorkflowExecution
|
89
|
+
# @return [Api::WorkflowService::V1::DescribeWorkflowExecutionResponse] Underlying protobuf description.
|
90
|
+
attr_reader :raw_description
|
91
|
+
|
92
|
+
# @!visibility private
|
93
|
+
def initialize(raw_description, data_converter)
|
94
|
+
super(raw_description.workflow_execution_info, data_converter)
|
95
|
+
@raw_description = raw_description
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Temporalio
|
4
|
+
class Client
|
5
|
+
# Representation of a count from a count workflows call.
|
6
|
+
class WorkflowExecutionCount
|
7
|
+
# @return [Integer] Approximate number of workflows matching the original query. If the query had a group-by
|
8
|
+
# clause, this is simply the sum of all the counts in {groups}.
|
9
|
+
attr_reader :count
|
10
|
+
|
11
|
+
# @return [Array<AggregationGroup>] Groups if the query had a group-by clause, or empty if not.
|
12
|
+
attr_reader :groups
|
13
|
+
|
14
|
+
# @!visibility private
|
15
|
+
def initialize(count, groups)
|
16
|
+
@count = count
|
17
|
+
@groups = groups
|
18
|
+
end
|
19
|
+
|
20
|
+
# Aggregation group if the workflow count query had a group-by clause.
|
21
|
+
class AggregationGroup
|
22
|
+
# @return [Integer] Approximate number of workflows matching the original query for this group.
|
23
|
+
attr_reader :count
|
24
|
+
|
25
|
+
# @return [Array<Object>] Search attribute values for this group.
|
26
|
+
attr_reader :group_values
|
27
|
+
|
28
|
+
# @!visibility private
|
29
|
+
def initialize(count, group_values)
|
30
|
+
@count = count
|
31
|
+
@group_values = group_values
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'temporalio/api'
|
4
|
+
|
5
|
+
module Temporalio
|
6
|
+
class Client
|
7
|
+
# Status of a workflow execution.
|
8
|
+
module WorkflowExecutionStatus
|
9
|
+
RUNNING = Api::Enums::V1::WorkflowExecutionStatus::WORKFLOW_EXECUTION_STATUS_RUNNING
|
10
|
+
COMPLETED = Api::Enums::V1::WorkflowExecutionStatus::WORKFLOW_EXECUTION_STATUS_COMPLETED
|
11
|
+
FAILED = Api::Enums::V1::WorkflowExecutionStatus::WORKFLOW_EXECUTION_STATUS_FAILED
|
12
|
+
CANCELED = Api::Enums::V1::WorkflowExecutionStatus::WORKFLOW_EXECUTION_STATUS_CANCELED
|
13
|
+
TERMINATED = Api::Enums::V1::WorkflowExecutionStatus::WORKFLOW_EXECUTION_STATUS_TERMINATED
|
14
|
+
CONTINUED_AS_NEW = Api::Enums::V1::WorkflowExecutionStatus::WORKFLOW_EXECUTION_STATUS_CONTINUED_AS_NEW
|
15
|
+
TIMED_OUT = Api::Enums::V1::WorkflowExecutionStatus::WORKFLOW_EXECUTION_STATUS_TIMED_OUT
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,389 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'securerandom'
|
4
|
+
require 'temporalio/api'
|
5
|
+
require 'temporalio/client/interceptor'
|
6
|
+
require 'temporalio/client/workflow_update_handle'
|
7
|
+
require 'temporalio/client/workflow_update_wait_stage'
|
8
|
+
require 'temporalio/error'
|
9
|
+
require 'temporalio/workflow_history'
|
10
|
+
|
11
|
+
module Temporalio
|
12
|
+
class Client
|
13
|
+
# Handle for interacting with a workflow. This is usually created via {Client.start_workflow} or
|
14
|
+
# {Client.workflow_handle}.
|
15
|
+
class WorkflowHandle
|
16
|
+
# @return [String] ID for the workflow.
|
17
|
+
attr_reader :id
|
18
|
+
|
19
|
+
# Run ID used for {signal}, {query}, and {start_update}/{execute_update} calls if present to ensure the
|
20
|
+
# signal/query/update happen on this exact run.
|
21
|
+
#
|
22
|
+
# This is only created via {Client.workflow_handle}. {Client.start_workflow} will not set this value.
|
23
|
+
#
|
24
|
+
# This cannot be mutated. If a different run ID is needed, {Client.workflow_handle} must be used instead.
|
25
|
+
#
|
26
|
+
# @return [String, nil] Run ID.
|
27
|
+
attr_reader :run_id
|
28
|
+
|
29
|
+
# Run ID used for {result} calls if present to ensure result is for a workflow starting from this run.
|
30
|
+
#
|
31
|
+
# When this handle is created via {Client.workflow_handle}, this is the same as {run_id}. When this handle is
|
32
|
+
# created via {Client.start_workflow}, this value will be the resulting run ID.
|
33
|
+
#
|
34
|
+
# This cannot be mutated. If a different run ID is needed, {Client.workflow_handle} must be used instead.
|
35
|
+
#
|
36
|
+
# @return [String, nil] Result run ID.
|
37
|
+
attr_reader :result_run_id
|
38
|
+
|
39
|
+
# Run ID used for some calls like {cancel} and {terminate} to ensure the cancel and terminate happen for a
|
40
|
+
# workflow ID on a chain started with this run ID.
|
41
|
+
#
|
42
|
+
# This can be set when using {Client.workflow_handle}. When {Client.start_workflow} is called without a start
|
43
|
+
# signal, this is set to the resulting run.
|
44
|
+
#
|
45
|
+
# This cannot be mutated. If a different first execution run ID is needed, {Client.workflow_handle} must be used
|
46
|
+
# instead.
|
47
|
+
#
|
48
|
+
# @return [String, nil] First execution run ID.
|
49
|
+
attr_reader :first_execution_run_id
|
50
|
+
|
51
|
+
# @!visibility private
|
52
|
+
def initialize(client:, id:, run_id:, result_run_id:, first_execution_run_id:)
|
53
|
+
@client = client
|
54
|
+
@id = id
|
55
|
+
@run_id = run_id
|
56
|
+
@result_run_id = result_run_id
|
57
|
+
@first_execution_run_id = first_execution_run_id
|
58
|
+
end
|
59
|
+
|
60
|
+
# Wait for the result of the workflow.
|
61
|
+
#
|
62
|
+
# This will use {result_run_id} if present to base the result on. To use another run ID, a new handle must be
|
63
|
+
# created via {Client.workflow_handle}.
|
64
|
+
#
|
65
|
+
# @param follow_runs [Boolean] If +true+, workflow runs will be continually fetched across retries and continue as
|
66
|
+
# new until the latest one is found. If +false+, the first result is used.
|
67
|
+
# @param rpc_options [RPCOptions, nil] Advanced RPC options.
|
68
|
+
#
|
69
|
+
# @return [Object] Result of the workflow after being converted by the data converter.
|
70
|
+
#
|
71
|
+
# @raise [Error::WorkflowFailedError] Workflow failed with +cause+ as the cause.
|
72
|
+
# @raise [Error::WorkflowContinuedAsNewError] Workflow continued as new and +follow_runs+ is +false+.
|
73
|
+
# @raise [Error::RPCError] RPC error from call.
|
74
|
+
def result(follow_runs: true, rpc_options: nil)
|
75
|
+
# Wait on the close event, following as needed
|
76
|
+
hist_run_id = result_run_id
|
77
|
+
loop do
|
78
|
+
# Get close event
|
79
|
+
event = fetch_history_events(
|
80
|
+
wait_new_event: true,
|
81
|
+
event_filter_type: Api::Enums::V1::HistoryEventFilterType::HISTORY_EVENT_FILTER_TYPE_CLOSE_EVENT,
|
82
|
+
skip_archival: true,
|
83
|
+
specific_run_id: hist_run_id,
|
84
|
+
rpc_options:
|
85
|
+
).next
|
86
|
+
|
87
|
+
# Check each close type'
|
88
|
+
case event.event_type
|
89
|
+
when :EVENT_TYPE_WORKFLOW_EXECUTION_COMPLETED
|
90
|
+
attrs = event.workflow_execution_completed_event_attributes
|
91
|
+
hist_run_id = attrs.new_execution_run_id
|
92
|
+
next if follow_runs && hist_run_id && !hist_run_id.empty?
|
93
|
+
|
94
|
+
return @client.data_converter.from_payloads(attrs.result).first
|
95
|
+
when :EVENT_TYPE_WORKFLOW_EXECUTION_FAILED
|
96
|
+
attrs = event.workflow_execution_failed_event_attributes
|
97
|
+
hist_run_id = attrs.new_execution_run_id
|
98
|
+
next if follow_runs && hist_run_id && !hist_run_id.empty?
|
99
|
+
|
100
|
+
raise Error::WorkflowFailedError.new, cause: @client.data_converter.from_failure(attrs.failure)
|
101
|
+
when :EVENT_TYPE_WORKFLOW_EXECUTION_CANCELED
|
102
|
+
attrs = event.workflow_execution_canceled_event_attributes
|
103
|
+
raise Error::WorkflowFailedError.new, 'Workflow execution canceled', cause: Error::CanceledError.new(
|
104
|
+
'Workflow execution canceled',
|
105
|
+
details: @client.data_converter.from_payloads(attrs&.details)
|
106
|
+
)
|
107
|
+
when :EVENT_TYPE_WORKFLOW_EXECUTION_TERMINATED
|
108
|
+
attrs = event.workflow_execution_terminated_event_attributes
|
109
|
+
raise Error::WorkflowFailedError.new, 'Workflow execution terminated', cause: Error::TerminatedError.new(
|
110
|
+
Internal::ProtoUtils.string_or(attrs.reason, 'Workflow execution terminated'),
|
111
|
+
details: @client.data_converter.from_payloads(attrs&.details)
|
112
|
+
)
|
113
|
+
when :EVENT_TYPE_WORKFLOW_EXECUTION_TIMED_OUT
|
114
|
+
attrs = event.workflow_execution_timed_out_event_attributes
|
115
|
+
hist_run_id = attrs.new_execution_run_id
|
116
|
+
next if follow_runs && hist_run_id && !hist_run_id.empty?
|
117
|
+
|
118
|
+
raise Error::WorkflowFailedError.new, 'Workflow execution timed out', cause: Error::TimeoutError.new(
|
119
|
+
'Workflow execution timed out',
|
120
|
+
type: Api::Enums::V1::TimeoutType::TIMEOUT_TYPE_START_TO_CLOSE,
|
121
|
+
last_heartbeat_details: []
|
122
|
+
)
|
123
|
+
when :EVENT_TYPE_WORKFLOW_EXECUTION_CONTINUED_AS_NEW
|
124
|
+
attrs = event.workflow_execution_continued_as_new_event_attributes
|
125
|
+
hist_run_id = attrs.new_execution_run_id
|
126
|
+
next if follow_runs && hist_run_id && !hist_run_id.empty?
|
127
|
+
|
128
|
+
# TODO: Use more specific error and decode failure
|
129
|
+
raise Error::WorkflowContinuedAsNewError.new(new_run_id: attrs.new_execution_run_id)
|
130
|
+
else
|
131
|
+
raise Error, "Unknown close event type: #{event.event_type}"
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
# Get workflow details. This will get details for the {run_id} if present. To use a different run ID, create a new
|
137
|
+
# handle via {Client.workflow_handle}.
|
138
|
+
#
|
139
|
+
# @param rpc_options [RPCOptions, nil] Advanced RPC options.
|
140
|
+
#
|
141
|
+
# @return [WorkflowExecution::Description] Workflow description.
|
142
|
+
#
|
143
|
+
# @raise [Error::RPCError] RPC error from call.
|
144
|
+
#
|
145
|
+
# @note Handles created as a result of {Client.start_workflow} will describe the latest workflow with the same
|
146
|
+
# workflow ID even if it is unrelated to the started workflow.
|
147
|
+
def describe(rpc_options: nil)
|
148
|
+
@client._impl.describe_workflow(Interceptor::DescribeWorkflowInput.new(
|
149
|
+
workflow_id: id,
|
150
|
+
run_id:,
|
151
|
+
rpc_options:
|
152
|
+
))
|
153
|
+
end
|
154
|
+
|
155
|
+
# Get workflow history. This is a helper on top of {fetch_history_events}.
|
156
|
+
#
|
157
|
+
# @param event_filter_type [Api::Enums::V1::HistoryEventFilterType] Types of events to fetch.
|
158
|
+
# @param skip_archival [Boolean] Whether to skip archival.
|
159
|
+
# @param rpc_options [RPCOptions, nil] Advanced RPC options.
|
160
|
+
#
|
161
|
+
# @return [WorkflowHistory] Workflow history.
|
162
|
+
#
|
163
|
+
# @raise [Error::RPCError] RPC error from call.
|
164
|
+
def fetch_history(
|
165
|
+
event_filter_type: Api::Enums::V1::HistoryEventFilterType::HISTORY_EVENT_FILTER_TYPE_ALL_EVENT,
|
166
|
+
skip_archival: false,
|
167
|
+
rpc_options: nil
|
168
|
+
)
|
169
|
+
WorkflowHistory.new(
|
170
|
+
fetch_history_events(
|
171
|
+
event_filter_type:,
|
172
|
+
skip_archival:,
|
173
|
+
rpc_options:
|
174
|
+
).to_a
|
175
|
+
)
|
176
|
+
end
|
177
|
+
|
178
|
+
# Fetch an enumerator of history events for this workflow. Internally this is done in paginated form, but it is
|
179
|
+
# presented as an enumerator.
|
180
|
+
#
|
181
|
+
# @param wait_new_event [Boolean] If +true+, when the end of the current set of events is reached but the workflow
|
182
|
+
# is not complete, this will wait for the next event. If +false+, the enumerable completes at the end of current
|
183
|
+
# history.
|
184
|
+
# @param event_filter_type [Api::Enums::V1::HistoryEventFilterType] Types of events to fetch.
|
185
|
+
# @param skip_archival [Boolean] Whether to skip archival.
|
186
|
+
# @param specific_run_id [String, nil] Run ID to fetch events for. Default is the {run_id}. Most users will not
|
187
|
+
# need to set this and instead use the one on the class.
|
188
|
+
# @param rpc_options [RPCOptions, nil] Advanced RPC options.
|
189
|
+
#
|
190
|
+
# @return [Enumerator<Api::History::V1::HistoryEvent>] Enumerable events.
|
191
|
+
#
|
192
|
+
# @raise [Error::RPCError] RPC error from call.
|
193
|
+
def fetch_history_events(
|
194
|
+
wait_new_event: false,
|
195
|
+
event_filter_type: Api::Enums::V1::HistoryEventFilterType::HISTORY_EVENT_FILTER_TYPE_ALL_EVENT,
|
196
|
+
skip_archival: false,
|
197
|
+
specific_run_id: run_id,
|
198
|
+
rpc_options: nil
|
199
|
+
)
|
200
|
+
@client._impl.fetch_workflow_history_events(Interceptor::FetchWorkflowHistoryEventsInput.new(
|
201
|
+
workflow_id: id,
|
202
|
+
run_id: specific_run_id,
|
203
|
+
wait_new_event:,
|
204
|
+
event_filter_type:,
|
205
|
+
skip_archival:,
|
206
|
+
rpc_options:
|
207
|
+
))
|
208
|
+
end
|
209
|
+
|
210
|
+
# Send a signal to the workflow. This will signal for {run_id} if present. To use a different run ID, create a new
|
211
|
+
# handle via {Client.workflow_handle}.
|
212
|
+
#
|
213
|
+
# @param signal [Workflow::Definition::Signal, Symbol, String] Signal definition or name.
|
214
|
+
# @param args [Array<Object>] Signal arguments.
|
215
|
+
# @param rpc_options [RPCOptions, nil] Advanced RPC options.
|
216
|
+
#
|
217
|
+
# @raise [Error::RPCError] RPC error from call.
|
218
|
+
#
|
219
|
+
# @note Handles created as a result of {Client.start_workflow} will signal the latest workflow with the same
|
220
|
+
# workflow ID even if it is unrelated to the started workflow.
|
221
|
+
def signal(signal, *args, rpc_options: nil)
|
222
|
+
@client._impl.signal_workflow(Interceptor::SignalWorkflowInput.new(
|
223
|
+
workflow_id: id,
|
224
|
+
run_id:,
|
225
|
+
signal:,
|
226
|
+
args:,
|
227
|
+
headers: {},
|
228
|
+
rpc_options:
|
229
|
+
))
|
230
|
+
end
|
231
|
+
|
232
|
+
# Query the workflow. This will query for {run_id} if present. To use a different run ID, create a new handle via
|
233
|
+
# {Client.workflow_handle}.
|
234
|
+
#
|
235
|
+
# @param query [Workflow::Definition::Query, Symbol, String] Query definition or name.
|
236
|
+
# @param args [Array<Object>] Query arguments.
|
237
|
+
# @param reject_condition [WorkflowQueryRejectCondition, nil] Condition for rejecting the query.
|
238
|
+
# @param rpc_options [RPCOptions, nil] Advanced RPC options.
|
239
|
+
#
|
240
|
+
# @return [Object, nil] Query result.
|
241
|
+
#
|
242
|
+
# @raise [Error::WorkflowQueryFailedError] The query on the workflow returned a failure.
|
243
|
+
# @raise [Error::WorkflowQueryRejectedError] A query reject condition was satisfied.
|
244
|
+
# @raise [Error::RPCError] RPC error from call.
|
245
|
+
#
|
246
|
+
# @note Handles created as a result of {Client.start_workflow} will query the latest workflow with the same
|
247
|
+
# workflow ID even if it is unrelated to the started workflow.
|
248
|
+
def query(
|
249
|
+
query,
|
250
|
+
*args,
|
251
|
+
reject_condition: @client.options.default_workflow_query_reject_condition,
|
252
|
+
rpc_options: nil
|
253
|
+
)
|
254
|
+
@client._impl.query_workflow(Interceptor::QueryWorkflowInput.new(
|
255
|
+
workflow_id: id,
|
256
|
+
run_id:,
|
257
|
+
query:,
|
258
|
+
args:,
|
259
|
+
reject_condition:,
|
260
|
+
headers: {},
|
261
|
+
rpc_options:
|
262
|
+
))
|
263
|
+
end
|
264
|
+
|
265
|
+
# Send an update request to the workflow and return a handle to it. This will target the workflow with {run_id} if
|
266
|
+
# present. To use a different run ID, create a new handle via {Client.workflow_handle}.
|
267
|
+
#
|
268
|
+
# @param update [Workflow::Definition::Update, Symbol, String] Update definition or name.
|
269
|
+
# @param args [Array<Object>] Update arguments.
|
270
|
+
# @param wait_for_stage [WorkflowUpdateWaitStage] Required stage to wait until returning. ADMITTED is not
|
271
|
+
# currently supported. See https://docs.temporal.io/workflows#update for more details.
|
272
|
+
# @param id [String] ID of the update.
|
273
|
+
# @param rpc_options [RPCOptions, nil] Advanced RPC options.
|
274
|
+
#
|
275
|
+
# @return [WorkflowUpdateHandle] The update handle.
|
276
|
+
#
|
277
|
+
# @raise [Error::WorkflowUpdateRPCTimeoutOrCanceledError] This update call timed out or was canceled. This doesn't
|
278
|
+
# mean the update itself was timed out or canceled.
|
279
|
+
# @raise [Error::RPCError] RPC error from call.
|
280
|
+
#
|
281
|
+
# @note Handles created as a result of {Client.start_workflow} will send updates the latest workflow with the same
|
282
|
+
# workflow ID even if it is unrelated to the started workflow.
|
283
|
+
def start_update(
|
284
|
+
update,
|
285
|
+
*args,
|
286
|
+
wait_for_stage:,
|
287
|
+
id: SecureRandom.uuid,
|
288
|
+
rpc_options: nil
|
289
|
+
)
|
290
|
+
@client._impl.start_workflow_update(Interceptor::StartWorkflowUpdateInput.new(
|
291
|
+
workflow_id: self.id,
|
292
|
+
run_id:,
|
293
|
+
update_id: id,
|
294
|
+
update:,
|
295
|
+
args:,
|
296
|
+
wait_for_stage:,
|
297
|
+
headers: {},
|
298
|
+
rpc_options:
|
299
|
+
))
|
300
|
+
end
|
301
|
+
|
302
|
+
# Send an update request to the workflow and wait for it to complete. This will target the workflow with {run_id}
|
303
|
+
# if present. To use a different run ID, create a new handle via {Client.workflow_handle}.
|
304
|
+
#
|
305
|
+
# @param update [Workflow::Definition::Update, Symbol, String] Update definition or name.
|
306
|
+
# @param args [Array<Object>] Update arguments.
|
307
|
+
# @param id [String] ID of the update.
|
308
|
+
# @param rpc_options [RPCOptions, nil] Advanced RPC options.
|
309
|
+
#
|
310
|
+
# @return [Object, nil] Update result.
|
311
|
+
#
|
312
|
+
# @raise [Error::WorkflowUpdateFailedError] If the update failed.
|
313
|
+
# @raise [Error::WorkflowUpdateRPCTimeoutOrCanceledError] This update call timed out or was canceled. This doesn't
|
314
|
+
# mean the update itself was timed out or canceled.
|
315
|
+
# @raise [Error::RPCError] RPC error from call.
|
316
|
+
#
|
317
|
+
# @note Handles created as a result of {Client.start_workflow} will send updates the latest workflow with the same
|
318
|
+
# workflow ID even if it is unrelated to the started workflow.
|
319
|
+
def execute_update(update, *args, id: SecureRandom.uuid, rpc_options: nil)
|
320
|
+
start_update(
|
321
|
+
update,
|
322
|
+
*args,
|
323
|
+
wait_for_stage: WorkflowUpdateWaitStage::COMPLETED,
|
324
|
+
id:,
|
325
|
+
rpc_options:
|
326
|
+
).result
|
327
|
+
end
|
328
|
+
|
329
|
+
# Get a handle for an update. The handle can be used to wait on the update result.
|
330
|
+
#
|
331
|
+
# @param id [String] ID of the update.
|
332
|
+
# @param specific_run_id [String, nil] Workflow run ID to get update handle for. Default is the {run_id}. Most
|
333
|
+
# users will not need to set this and instead use the one on the class.
|
334
|
+
#
|
335
|
+
# @return [WorkflowUpdateHandle] The update handle.
|
336
|
+
def update_handle(id, specific_run_id: run_id)
|
337
|
+
WorkflowUpdateHandle.new(
|
338
|
+
client: @client,
|
339
|
+
id:,
|
340
|
+
workflow_id: self.id,
|
341
|
+
workflow_run_id: specific_run_id,
|
342
|
+
known_outcome: nil
|
343
|
+
)
|
344
|
+
end
|
345
|
+
|
346
|
+
# Cancel the workflow. This will issue a cancellation for {run_id} if present. This call will make sure to use the
|
347
|
+
# run chain starting from {first_execution_run_id} if present. To create handles with these values, use
|
348
|
+
# {Client.workflow_handle}.
|
349
|
+
#
|
350
|
+
# @param rpc_options [RPCOptions, nil] Advanced RPC options.
|
351
|
+
#
|
352
|
+
# @raise [Error::RPCError] RPC error from call.
|
353
|
+
#
|
354
|
+
# @note Handles created as a result of signal with start will cancel the latest workflow with the same workflow ID
|
355
|
+
# even if it is unrelated to the started workflow.
|
356
|
+
def cancel(rpc_options: nil)
|
357
|
+
@client._impl.cancel_workflow(Interceptor::CancelWorkflowInput.new(
|
358
|
+
workflow_id: id,
|
359
|
+
run_id:,
|
360
|
+
first_execution_run_id:,
|
361
|
+
rpc_options:
|
362
|
+
))
|
363
|
+
end
|
364
|
+
|
365
|
+
# Terminate the workflow. This will issue a termination for {run_id} if present. This call will make sure to use
|
366
|
+
# the run chain starting from {first_execution_run_id} if present. To create handles with these values, use
|
367
|
+
# {Client.workflow_handle}.
|
368
|
+
#
|
369
|
+
# @param reason [String, nil] Reason for the termination.
|
370
|
+
# @param details [Array<Object>] Details to store on the termination.
|
371
|
+
# @param rpc_options [RPCOptions, nil] Advanced RPC options.
|
372
|
+
#
|
373
|
+
# @raise [Error::RPCError] RPC error from call.
|
374
|
+
#
|
375
|
+
# @note Handles created as a result of signal with start will terminate the latest workflow with the same workflow
|
376
|
+
# ID even if it is unrelated to the started workflow.
|
377
|
+
def terminate(reason = nil, details: [], rpc_options: nil)
|
378
|
+
@client._impl.terminate_workflow(Interceptor::TerminateWorkflowInput.new(
|
379
|
+
workflow_id: id,
|
380
|
+
run_id:,
|
381
|
+
first_execution_run_id:,
|
382
|
+
reason:,
|
383
|
+
details:,
|
384
|
+
rpc_options:
|
385
|
+
))
|
386
|
+
end
|
387
|
+
end
|
388
|
+
end
|
389
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'temporalio/api'
|
4
|
+
|
5
|
+
module Temporalio
|
6
|
+
class Client
|
7
|
+
# Whether a query should be rejected in certain conditions.
|
8
|
+
module WorkflowQueryRejectCondition
|
9
|
+
NONE = Api::Enums::V1::QueryRejectCondition::QUERY_REJECT_CONDITION_NONE
|
10
|
+
NOT_OPEN = Api::Enums::V1::QueryRejectCondition::QUERY_REJECT_CONDITION_NOT_OPEN
|
11
|
+
NOT_COMPLETED_CLEANLY = Api::Enums::V1::QueryRejectCondition::QUERY_REJECT_CONDITION_NOT_COMPLETED_CLEANLY
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|