diff --git a/Makefile b/Makefile index 6967cb5bb..6c3d76fac 100644 --- a/Makefile +++ b/Makefile @@ -6,4 +6,10 @@ PROTO_OUT := lib/gen proto: $(foreach PROTO_DIR,$(PROTO_DIRS),bundle exec grpc_tools_ruby_protoc -Iproto --ruby_out=$(PROTO_OUT) --grpc_out=$(PROTO_OUT) $(PROTO_DIR)*.proto;) + # Need to only load imports if not disabled + sed -i "/require 'temporal/ s|\(.*\)|\1 unless ENV['COINBASE_TEMPORAL_RUBY_DISABLE_PROTO_LOAD'] == '1'|" \ + lib/gen/temporal/api/operatorservice/v1/service_services_pb.rb + sed -i "/require 'temporal/ s|\(.*\)|\1 unless ENV['COINBASE_TEMPORAL_RUBY_DISABLE_PROTO_LOAD'] == '1'|" \ + lib/gen/temporal/api/workflowservice/v1/service_services_pb.rb + .PHONY: proto diff --git a/lib/gen/temporal/api/operatorservice/v1/service_services_pb.rb b/lib/gen/temporal/api/operatorservice/v1/service_services_pb.rb index 44a8c5713..1dad652f0 100644 --- a/lib/gen/temporal/api/operatorservice/v1/service_services_pb.rb +++ b/lib/gen/temporal/api/operatorservice/v1/service_services_pb.rb @@ -25,7 +25,7 @@ # require 'grpc' -require 'temporal/api/operatorservice/v1/service_pb' +require 'temporal/api/operatorservice/v1/service_pb' unless ENV['COINBASE_TEMPORAL_RUBY_DISABLE_PROTO_LOAD'] == '1' module Temporalio module Api diff --git a/lib/gen/temporal/api/workflowservice/v1/service_services_pb.rb b/lib/gen/temporal/api/workflowservice/v1/service_services_pb.rb index 3acb9d264..e7a42c930 100644 --- a/lib/gen/temporal/api/workflowservice/v1/service_services_pb.rb +++ b/lib/gen/temporal/api/workflowservice/v1/service_services_pb.rb @@ -25,7 +25,7 @@ # require 'grpc' -require 'temporal/api/workflowservice/v1/service_pb' +require 'temporal/api/workflowservice/v1/service_pb' unless ENV['COINBASE_TEMPORAL_RUBY_DISABLE_PROTO_LOAD'] == '1' module Temporalio module Api diff --git a/lib/temporal.rb b/lib/temporal.rb index b9f49d559..91b69cb31 100644 --- a/lib/temporal.rb +++ b/lib/temporal.rb @@ -1,5 +1,7 @@ -# Protoc wants all of its generated files on the LOAD_PATH -$LOAD_PATH << File.expand_path('./gen', __dir__) +# Protoc wants all of its generated files on the LOAD_PATH. Only require protos if not disabled. +unless ENV['COINBASE_TEMPORAL_RUBY_DISABLE_PROTO_LOAD'] == '1' + $LOAD_PATH << File.expand_path('./gen', __dir__) +end require 'securerandom' require 'forwardable' diff --git a/lib/temporal/client.rb b/lib/temporal/client.rb index fc390e92b..b4f7dd782 100644 --- a/lib/temporal/client.rb +++ b/lib/temporal/client.rb @@ -230,25 +230,31 @@ def await_workflow_result(workflow, workflow_id:, run_id: nil, timeout: nil, nam execution_options = ExecutionOptions.new(workflow, options, config.default_execution_options) max_timeout = Temporal::Connection::GRPC::SERVER_MAX_GET_WORKFLOW_EXECUTION_HISTORY_POLL history_response = nil - begin - history_response = connection.get_workflow_execution_history( - namespace: execution_options.namespace, - workflow_id: workflow_id, - run_id: run_id, - wait_for_new_event: true, - event_type: :close, - timeout: timeout || max_timeout, - ) - rescue GRPC::DeadlineExceeded => e - message = if timeout - "Timed out after your specified limit of timeout: #{timeout} seconds" - else - "Timed out after #{max_timeout} seconds, which is the maximum supported amount." + closed_event = nil + loop do + begin + history_response = connection.get_workflow_execution_history( + namespace: execution_options.namespace, + workflow_id: workflow_id, + run_id: run_id, + wait_for_new_event: true, + event_type: :close, + timeout: timeout || max_timeout, + ) + rescue GRPC::DeadlineExceeded => e + message = if timeout + "Timed out after your specified limit of timeout: #{timeout} seconds" + else + "Timed out after #{max_timeout} seconds, which is the maximum supported amount." + end + raise TimeoutError.new(message) end - raise TimeoutError.new(message) + history = Workflow::History.new(history_response.history.events) + closed_event = history.events.first + + break if closed_event end - history = Workflow::History.new(history_response.history.events) - closed_event = history.events.first + case closed_event.type when 'WORKFLOW_EXECUTION_COMPLETED' payloads = closed_event.attributes.result diff --git a/lib/temporal/connection/grpc.rb b/lib/temporal/connection/grpc.rb index 1f817f515..eb2e23f64 100644 --- a/lib/temporal/connection/grpc.rb +++ b/lib/temporal/connection/grpc.rb @@ -3,11 +3,6 @@ require 'google/protobuf/well_known_types' require 'securerandom' require 'json' -require 'gen/temporal/api/filter/v1/message_pb' -require 'gen/temporal/api/workflowservice/v1/service_services_pb' -require 'gen/temporal/api/operatorservice/v1/service_services_pb' -require 'gen/temporal/api/enums/v1/workflow_pb' -require 'gen/temporal/api/enums/v1/common_pb' require 'temporal/connection/errors' require 'temporal/connection/interceptors/client_name_version_interceptor' require 'temporal/connection/serializer' @@ -16,6 +11,17 @@ require 'temporal/connection/serializer/schedule' require 'temporal/connection/serializer/workflow_id_reuse_policy' +# Only require protos if not disabled. This env var is commonly set to work alongside the temporalio/sdk-ruby project. +unless ENV['COINBASE_TEMPORAL_RUBY_DISABLE_PROTO_LOAD'] == '1' + require 'gen/temporal/api/filter/v1/message_pb' + require 'gen/temporal/api/enums/v1/workflow_pb' + require 'gen/temporal/api/enums/v1/common_pb' +end + +# These are gRPC stubs, not protos, and therefore are not disabled when protos are +require 'gen/temporal/api/workflowservice/v1/service_services_pb' +require 'gen/temporal/api/operatorservice/v1/service_services_pb' + module Temporal module Connection class GRPC diff --git a/lib/temporal/connection/serializer/base.rb b/lib/temporal/connection/serializer/base.rb index 79e8767a8..595a73b6e 100644 --- a/lib/temporal/connection/serializer/base.rb +++ b/lib/temporal/connection/serializer/base.rb @@ -1,6 +1,10 @@ require 'oj' -require 'gen/temporal/api/common/v1/message_pb' -require 'gen/temporal/api/command/v1/message_pb' + +# Only require protos if not disabled +unless ENV['COINBASE_TEMPORAL_RUBY_DISABLE_PROTO_LOAD'] == '1' + require 'gen/temporal/api/common/v1/message_pb' + require 'gen/temporal/api/command/v1/message_pb' +end module Temporal module Connection diff --git a/lib/temporal/connection/serializer/schedule_overlap_policy.rb b/lib/temporal/connection/serializer/schedule_overlap_policy.rb index a866c8ee7..8e7aba329 100644 --- a/lib/temporal/connection/serializer/schedule_overlap_policy.rb +++ b/lib/temporal/connection/serializer/schedule_overlap_policy.rb @@ -1,5 +1,10 @@ require "temporal/connection/serializer/base" +# Only require protos if not disabled +unless ENV['COINBASE_TEMPORAL_RUBY_DISABLE_PROTO_LOAD'] == '1' + require "gen/temporal/api/enums/v1/schedule_pb" +end + module Temporal module Connection module Serializer diff --git a/lib/temporal/testing/replay_tester.rb b/lib/temporal/testing/replay_tester.rb index 6a98c86e9..a08617a89 100644 --- a/lib/temporal/testing/replay_tester.rb +++ b/lib/temporal/testing/replay_tester.rb @@ -1,4 +1,3 @@ -require "gen/temporal/api/history/v1/message_pb" require "json" require "temporal/errors" require "temporal/metadata/workflow_task" @@ -6,6 +5,11 @@ require "temporal/workflow/executor" require "temporal/workflow/stack_trace_tracker" +# Only require protos if not disabled +unless ENV['COINBASE_TEMPORAL_RUBY_DISABLE_PROTO_LOAD'] == '1' + require "gen/temporal/api/history/v1/message_pb" +end + module Temporal module Testing class ReplayError < StandardError diff --git a/spec/unit/lib/temporal/client_spec.rb b/spec/unit/lib/temporal/client_spec.rb index a0ba4dc1a..6e0b53e87 100644 --- a/spec/unit/lib/temporal/client_spec.rb +++ b/spec/unit/lib/temporal/client_spec.rb @@ -449,6 +449,31 @@ class NamespacedWorkflow < Temporal::Workflow ) end + it 'retries if there is till there is no closed event' do + completed_event = Fabricate(:workflow_completed_event, result: nil) + response_with_no_closed_event = Fabricate(:workflow_execution_history, events: []) + response_with_closed_event = Fabricate(:workflow_execution_history, events: [completed_event]) + + expect(connection) + .to receive(:get_workflow_execution_history) + .with( + namespace: 'some-namespace', + workflow_id: workflow_id, + run_id: run_id, + wait_for_new_event: true, + event_type: :close, + timeout: 30, + ) + .and_return(response_with_no_closed_event, response_with_closed_event) + + + subject.await_workflow_result( + NamespacedWorkflow, + workflow_id: workflow_id, + run_id: run_id, + ) + end + it 'can override the namespace' do completed_event = Fabricate(:workflow_completed_event, result: nil) response = Fabricate(:workflow_execution_history, events: [completed_event])