From f7dcfd71b6feecea244f77c910fea1039539dd9e Mon Sep 17 00:00:00 2001 From: Tim Hsu Date: Thu, 30 Sep 2021 06:56:29 +0000 Subject: [PATCH 1/3] Add parent close policy --- .../serializer/parent_close_policy.rb | 20 ++++++++++++++ .../serializer/start_child_workflow.rb | 1 + lib/temporal/execution_options.rb | 10 ++++++- lib/temporal/parent_close_policy.rb | 20 ++++++++++++++ lib/temporal/workflow/context.rb | 1 + .../serializer/parent_close_policy_spec.rb | 24 +++++++++++++++++ .../lib/temporal/parent_close_policy_spec.rb | 27 +++++++++++++++++++ 7 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 lib/temporal/connection/serializer/parent_close_policy.rb create mode 100644 lib/temporal/parent_close_policy.rb create mode 100644 spec/unit/lib/temporal/connection/serializer/parent_close_policy_spec.rb create mode 100644 spec/unit/lib/temporal/parent_close_policy_spec.rb diff --git a/lib/temporal/connection/serializer/parent_close_policy.rb b/lib/temporal/connection/serializer/parent_close_policy.rb new file mode 100644 index 00000000..4a4ea796 --- /dev/null +++ b/lib/temporal/connection/serializer/parent_close_policy.rb @@ -0,0 +1,20 @@ +require 'temporal/connection/serializer/base' + +module Temporal + module Connection + module Serializer + class ParentClosePolicy < Base + def to_proto + return Temporal::Api::Enums::V1::ParentClosePolicy::PARENT_CLOSE_POLICY_UNSPECIFIED unless object + mapping = { + abandon: Temporal::Api::Enums::V1::ParentClosePolicy::PARENT_CLOSE_POLICY_ABANDON, + terminate: Temporal::Api::Enums::V1::ParentClosePolicy::PARENT_CLOSE_POLICY_TERMINATE, + request_cancel: Temporal::Api::Enums::V1::ParentClosePolicy::PARENT_CLOSE_POLICY_REQUEST_CANCEL, + }.compact + + mapping[object.policy] + end + end + end + end +end diff --git a/lib/temporal/connection/serializer/start_child_workflow.rb b/lib/temporal/connection/serializer/start_child_workflow.rb index 55312e50..0f27641c 100644 --- a/lib/temporal/connection/serializer/start_child_workflow.rb +++ b/lib/temporal/connection/serializer/start_child_workflow.rb @@ -22,6 +22,7 @@ def to_proto workflow_run_timeout: object.timeouts[:run], workflow_task_timeout: object.timeouts[:task], retry_policy: Temporal::Connection::Serializer::RetryPolicy.new(object.retry_policy).to_proto, + parent_close_policy: Temporal::Connection::Serializer::ParentClosePolicy.new(object.parent_close_policy).to_proto, header: serialize_headers(object.headers) ) ) diff --git a/lib/temporal/execution_options.rb b/lib/temporal/execution_options.rb index 6fcaf371..7d2a4d7a 100644 --- a/lib/temporal/execution_options.rb +++ b/lib/temporal/execution_options.rb @@ -3,7 +3,7 @@ module Temporal class ExecutionOptions - attr_reader :name, :namespace, :task_queue, :retry_policy, :timeouts, :headers + attr_reader :name, :namespace, :task_queue, :retry_policy, :parent_close_policy, :timeouts, :headers def initialize(object, options, defaults = nil) # Options are treated as overrides and take precedence @@ -11,6 +11,7 @@ def initialize(object, options, defaults = nil) @namespace = options[:namespace] @task_queue = options[:task_queue] || options[:task_list] @retry_policy = options[:retry_policy] || {} + @parent_close_policy = options[:parent_close_policy] || {} @timeouts = options[:timeouts] || {} @headers = options[:headers] || {} @@ -38,6 +39,13 @@ def initialize(object, options, defaults = nil) @retry_policy.validate! end + if @parent_close_policy.empty? + @parent_close_policy = nil + else + @parent_close_policy = Temporal::ParentClosePolicy.new(@parent_close_policy) + @parent_close_policy.validate! + end + freeze end diff --git a/lib/temporal/parent_close_policy.rb b/lib/temporal/parent_close_policy.rb new file mode 100644 index 00000000..5d23ce6f --- /dev/null +++ b/lib/temporal/parent_close_policy.rb @@ -0,0 +1,20 @@ +require 'temporal/errors' + +module Temporal + # See https://docs.temporal.io/docs/content/what-is-a-parent-close-policy/ for more information + class ParentClosePolicy + class InvalidParentClosePolicy < ClientError; end + + attr_reader :policy + + def initialize(policy) + @policy = policy + end + + def validate! + unless %i[terminate abandon request_cancel].include?(@policy) + raise InvalidParentClosePolicy, 'Invalid parent close policy, only :abandon, :terminate, :request_cancel are allowed' + end + end + end +end diff --git a/lib/temporal/workflow/context.rb b/lib/temporal/workflow/context.rb index d4541840..6425b6e4 100644 --- a/lib/temporal/workflow/context.rb +++ b/lib/temporal/workflow/context.rb @@ -110,6 +110,7 @@ def execute_workflow(workflow_class, *input, **args) namespace: execution_options.namespace, task_queue: execution_options.task_queue, retry_policy: execution_options.retry_policy, + parent_close_policy: execution_options.parent_close_policy, timeouts: execution_options.timeouts, headers: execution_options.headers ) diff --git a/spec/unit/lib/temporal/connection/serializer/parent_close_policy_spec.rb b/spec/unit/lib/temporal/connection/serializer/parent_close_policy_spec.rb new file mode 100644 index 00000000..94af74f1 --- /dev/null +++ b/spec/unit/lib/temporal/connection/serializer/parent_close_policy_spec.rb @@ -0,0 +1,24 @@ +require 'temporal/parent_close_policy' +require 'temporal/connection/serializer/parent_close_policy' + +describe Temporal::Connection::Serializer::ParentClosePolicy do + describe 'to_proto' do + let(:terminate_policy) { Temporal::ParentClosePolicy.new(:terminate) } + let(:abandon_policy) { Temporal::ParentClosePolicy.new(:abandon) } + let(:request_cancel_policy) { Temporal::ParentClosePolicy.new(:request_cancel) } + + it 'converts to proto' do + expect do + described_class.new(terminate_policy).to_proto + end.not_to raise_error + + expect do + described_class.new(abandon_policy).to_proto + end.not_to raise_error + + expect do + described_class.new(request_cancel_policy).to_proto + end.not_to raise_error + end + end +end diff --git a/spec/unit/lib/temporal/parent_close_policy_spec.rb b/spec/unit/lib/temporal/parent_close_policy_spec.rb new file mode 100644 index 00000000..49fa6e96 --- /dev/null +++ b/spec/unit/lib/temporal/parent_close_policy_spec.rb @@ -0,0 +1,27 @@ +require 'temporal/parent_close_policy' + +describe Temporal::ParentClosePolicy do + describe '#validate!' do + subject { described_class.new(param) } + + context 'with valid param' do + %i[abandon terminate request_cancel].each do |policy| + context "with #{policy}" do + let(:param) { policy } + + it 'does not raise' do + expect { subject.validate! }.not_to raise_error + end + end + end + end + + context 'with invalid param' do + let(:param) { :coinbase } + + it 'does not raise' do + expect { subject.validate! }.to raise_error(described_class::InvalidParentClosePolicy) + end + end + end +end From 0986dae25d1773bb9ea203351b5378f402391166 Mon Sep 17 00:00:00 2001 From: Tim Hsu Date: Thu, 30 Sep 2021 07:25:07 +0000 Subject: [PATCH 2/3] Fix missing require --- lib/temporal/connection/serializer/start_child_workflow.rb | 1 + lib/temporal/execution_options.rb | 1 + 2 files changed, 2 insertions(+) diff --git a/lib/temporal/connection/serializer/start_child_workflow.rb b/lib/temporal/connection/serializer/start_child_workflow.rb index 0f27641c..74060b6d 100644 --- a/lib/temporal/connection/serializer/start_child_workflow.rb +++ b/lib/temporal/connection/serializer/start_child_workflow.rb @@ -1,5 +1,6 @@ require 'temporal/connection/serializer/base' require 'temporal/connection/serializer/retry_policy' +require 'temporal/connection/serializer/parent_close_policy' require 'temporal/concerns/payloads' module Temporal diff --git a/lib/temporal/execution_options.rb b/lib/temporal/execution_options.rb index 7d2a4d7a..71ef3236 100644 --- a/lib/temporal/execution_options.rb +++ b/lib/temporal/execution_options.rb @@ -1,5 +1,6 @@ require 'temporal/concerns/executable' require 'temporal/retry_policy' +require 'temporal/parent_close_policy' module Temporal class ExecutionOptions From bfd4706971f8592df3a3863c23b6699f60025901 Mon Sep 17 00:00:00 2001 From: Tim Hsu Date: Thu, 30 Sep 2021 09:12:28 +0000 Subject: [PATCH 3/3] Add new param to start child workflow --- lib/temporal/workflow/command.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/temporal/workflow/command.rb b/lib/temporal/workflow/command.rb index 0f0d6ed9..62876cf7 100644 --- a/lib/temporal/workflow/command.rb +++ b/lib/temporal/workflow/command.rb @@ -3,7 +3,7 @@ class Workflow module Command # TODO: Move these classes into their own directories under workflow/command/* ScheduleActivity = Struct.new(:activity_type, :activity_id, :input, :namespace, :task_queue, :retry_policy, :timeouts, :headers, keyword_init: true) - StartChildWorkflow = Struct.new(:workflow_type, :workflow_id, :input, :namespace, :task_queue, :retry_policy, :timeouts, :headers, keyword_init: true) + StartChildWorkflow = Struct.new(:workflow_type, :workflow_id, :input, :namespace, :task_queue, :retry_policy, :parent_close_policy, :timeouts, :headers, keyword_init: true) ContinueAsNew = Struct.new(:workflow_type, :task_queue, :input, :timeouts, :retry_policy, :headers, keyword_init: true) RequestActivityCancellation = Struct.new(:activity_id, keyword_init: true) RecordMarker = Struct.new(:name, :details, keyword_init: true)