temporalio 0.2.0-x86_64-linux → 0.3.0-x86_64-linux
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/.yardopts +2 -0
- data/Gemfile +23 -0
- data/Rakefile +101 -0
- data/lib/temporalio/activity/complete_async_error.rb +1 -1
- data/lib/temporalio/activity/context.rb +5 -2
- data/lib/temporalio/activity/definition.rb +163 -65
- data/lib/temporalio/activity/info.rb +22 -21
- data/lib/temporalio/activity.rb +2 -59
- data/lib/temporalio/api/activity/v1/message.rb +25 -0
- data/lib/temporalio/api/cloud/account/v1/message.rb +28 -0
- data/lib/temporalio/api/cloud/cloudservice/v1/request_response.rb +34 -1
- data/lib/temporalio/api/cloud/cloudservice/v1/service.rb +1 -1
- data/lib/temporalio/api/cloud/identity/v1/message.rb +6 -1
- data/lib/temporalio/api/cloud/namespace/v1/message.rb +8 -1
- data/lib/temporalio/api/cloud/nexus/v1/message.rb +31 -0
- data/lib/temporalio/api/cloud/operation/v1/message.rb +2 -1
- data/lib/temporalio/api/cloud/region/v1/message.rb +2 -1
- 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/common/v1/message.rb +7 -1
- data/lib/temporalio/api/enums/v1/event_type.rb +1 -1
- data/lib/temporalio/api/enums/v1/failed_cause.rb +1 -1
- data/lib/temporalio/api/enums/v1/reset.rb +1 -1
- data/lib/temporalio/api/history/v1/message.rb +1 -1
- data/lib/temporalio/api/nexus/v1/message.rb +2 -2
- data/lib/temporalio/api/operatorservice/v1/service.rb +1 -1
- data/lib/temporalio/api/payload_visitor.rb +1513 -0
- data/lib/temporalio/api/schedule/v1/message.rb +2 -1
- 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/workflow/v1/message.rb +1 -1
- data/lib/temporalio/api/workflowservice/v1/request_response.rb +17 -2
- data/lib/temporalio/api/workflowservice/v1/service.rb +1 -1
- data/lib/temporalio/api.rb +1 -0
- data/lib/temporalio/cancellation.rb +34 -14
- data/lib/temporalio/client/async_activity_handle.rb +12 -37
- data/lib/temporalio/client/connection/cloud_service.rb +309 -231
- data/lib/temporalio/client/connection/operator_service.rb +36 -84
- data/lib/temporalio/client/connection/service.rb +6 -5
- data/lib/temporalio/client/connection/test_service.rb +111 -0
- data/lib/temporalio/client/connection/workflow_service.rb +264 -441
- data/lib/temporalio/client/connection.rb +90 -44
- data/lib/temporalio/client/interceptor.rb +160 -60
- data/lib/temporalio/client/schedule.rb +967 -0
- data/lib/temporalio/client/schedule_handle.rb +126 -0
- data/lib/temporalio/client/workflow_execution.rb +7 -10
- data/lib/temporalio/client/workflow_handle.rb +38 -95
- data/lib/temporalio/client/workflow_update_handle.rb +3 -5
- data/lib/temporalio/client.rb +122 -42
- data/lib/temporalio/common_enums.rb +17 -0
- data/lib/temporalio/converters/data_converter.rb +4 -7
- data/lib/temporalio/converters/failure_converter.rb +5 -3
- data/lib/temporalio/converters/payload_converter/composite.rb +4 -0
- data/lib/temporalio/converters/payload_converter.rb +6 -8
- data/lib/temporalio/converters/raw_value.rb +20 -0
- data/lib/temporalio/error/failure.rb +1 -1
- data/lib/temporalio/error.rb +10 -2
- data/lib/temporalio/internal/bridge/3.2/temporalio_bridge.so +0 -0
- data/lib/temporalio/internal/bridge/3.3/temporalio_bridge.so +0 -0
- data/lib/temporalio/internal/bridge/{3.1 → 3.4}/temporalio_bridge.so +0 -0
- data/lib/temporalio/internal/bridge/api/core_interface.rb +5 -1
- data/lib/temporalio/internal/bridge/api/nexus/nexus.rb +33 -0
- data/lib/temporalio/internal/bridge/api/workflow_activation/workflow_activation.rb +5 -1
- data/lib/temporalio/internal/bridge/api/workflow_commands/workflow_commands.rb +4 -1
- data/lib/temporalio/internal/bridge/client.rb +11 -6
- data/lib/temporalio/internal/bridge/testing.rb +20 -0
- data/lib/temporalio/internal/bridge/worker.rb +2 -0
- data/lib/temporalio/internal/bridge.rb +1 -1
- data/lib/temporalio/internal/client/implementation.rb +245 -70
- data/lib/temporalio/internal/metric.rb +122 -0
- data/lib/temporalio/internal/proto_utils.rb +86 -7
- data/lib/temporalio/internal/worker/activity_worker.rb +52 -24
- data/lib/temporalio/internal/worker/multi_runner.rb +51 -7
- data/lib/temporalio/internal/worker/workflow_instance/child_workflow_handle.rb +54 -0
- data/lib/temporalio/internal/worker/workflow_instance/context.rb +329 -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 +196 -0
- data/lib/temporalio/metric.rb +109 -0
- data/lib/temporalio/retry_policy.rb +37 -14
- data/lib/temporalio/runtime.rb +118 -75
- data/lib/temporalio/search_attributes.rb +80 -37
- data/lib/temporalio/testing/activity_environment.rb +2 -2
- data/lib/temporalio/testing/workflow_environment.rb +251 -5
- data/lib/temporalio/version.rb +1 -1
- data/lib/temporalio/worker/activity_executor/thread_pool.rb +9 -217
- data/lib/temporalio/worker/activity_executor.rb +3 -3
- data/lib/temporalio/worker/interceptor.rb +340 -66
- data/lib/temporalio/worker/thread_pool.rb +237 -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.rb +201 -30
- 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 +523 -0
- data/lib/temporalio.rb +4 -0
- data/temporalio.gemspec +2 -2
- metadata +54 -6
| @@ -0,0 +1,122 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'singleton'
         | 
| 4 | 
            +
            require 'temporalio/internal/bridge'
         | 
| 5 | 
            +
            require 'temporalio/metric'
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            module Temporalio
         | 
| 8 | 
            +
              module Internal
         | 
| 9 | 
            +
                class Metric < Temporalio::Metric
         | 
| 10 | 
            +
                  attr_reader :metric_type, :name, :description, :unit, :value_type
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  def initialize(metric_type:, name:, description:, unit:, value_type:, bridge:, bridge_attrs:) # rubocop:disable Lint/MissingSuper
         | 
| 13 | 
            +
                    @metric_type = metric_type
         | 
| 14 | 
            +
                    @name = name
         | 
| 15 | 
            +
                    @description = description
         | 
| 16 | 
            +
                    @unit = unit
         | 
| 17 | 
            +
                    @value_type = value_type
         | 
| 18 | 
            +
                    @bridge = bridge
         | 
| 19 | 
            +
                    @bridge_attrs = bridge_attrs
         | 
| 20 | 
            +
                  end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                  def record(value, additional_attributes: nil)
         | 
| 23 | 
            +
                    bridge_attrs = @bridge_attrs
         | 
| 24 | 
            +
                    bridge_attrs = @bridge_attrs.with_additional(additional_attributes) if additional_attributes
         | 
| 25 | 
            +
                    @bridge.record_value(value, bridge_attrs)
         | 
| 26 | 
            +
                  end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                  def with_additional_attributes(additional_attributes)
         | 
| 29 | 
            +
                    Metric.new(
         | 
| 30 | 
            +
                      metric_type:,
         | 
| 31 | 
            +
                      name:,
         | 
| 32 | 
            +
                      description:,
         | 
| 33 | 
            +
                      unit:,
         | 
| 34 | 
            +
                      value_type:,
         | 
| 35 | 
            +
                      bridge: @bridge,
         | 
| 36 | 
            +
                      bridge_attrs: @bridge_attrs.with_additional(additional_attributes)
         | 
| 37 | 
            +
                    )
         | 
| 38 | 
            +
                  end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                  class Meter < Temporalio::Metric::Meter
         | 
| 41 | 
            +
                    def self.create_from_runtime(runtime)
         | 
| 42 | 
            +
                      bridge = Bridge::Metric::Meter.new(runtime._core_runtime)
         | 
| 43 | 
            +
                      return nil unless bridge
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                      Meter.new(bridge, bridge.default_attributes)
         | 
| 46 | 
            +
                    end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                    def initialize(bridge, bridge_attrs) # rubocop:disable Lint/MissingSuper
         | 
| 49 | 
            +
                      @bridge = bridge
         | 
| 50 | 
            +
                      @bridge_attrs = bridge_attrs
         | 
| 51 | 
            +
                    end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                    def create_metric(
         | 
| 54 | 
            +
                      metric_type,
         | 
| 55 | 
            +
                      name,
         | 
| 56 | 
            +
                      description: nil,
         | 
| 57 | 
            +
                      unit: nil,
         | 
| 58 | 
            +
                      value_type: :integer
         | 
| 59 | 
            +
                    )
         | 
| 60 | 
            +
                      Metric.new(
         | 
| 61 | 
            +
                        metric_type:,
         | 
| 62 | 
            +
                        name:,
         | 
| 63 | 
            +
                        description:,
         | 
| 64 | 
            +
                        unit:,
         | 
| 65 | 
            +
                        value_type:,
         | 
| 66 | 
            +
                        bridge: Bridge::Metric.new(@bridge, metric_type, name, description, unit, value_type),
         | 
| 67 | 
            +
                        bridge_attrs: @bridge_attrs
         | 
| 68 | 
            +
                      )
         | 
| 69 | 
            +
                    end
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                    def with_additional_attributes(additional_attributes)
         | 
| 72 | 
            +
                      Meter.new(@bridge, @bridge_attrs.with_additional(additional_attributes))
         | 
| 73 | 
            +
                    end
         | 
| 74 | 
            +
                  end
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                  class NullMeter < Temporalio::Metric::Meter
         | 
| 77 | 
            +
                    include Singleton
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                    def initialize # rubocop:disable Style/RedundantInitialize,Lint/MissingSuper
         | 
| 80 | 
            +
                    end
         | 
| 81 | 
            +
             | 
| 82 | 
            +
                    def create_metric(
         | 
| 83 | 
            +
                      metric_type,
         | 
| 84 | 
            +
                      name,
         | 
| 85 | 
            +
                      description: nil,
         | 
| 86 | 
            +
                      unit: nil,
         | 
| 87 | 
            +
                      value_type: :integer
         | 
| 88 | 
            +
                    )
         | 
| 89 | 
            +
                      NullMetric.new(
         | 
| 90 | 
            +
                        metric_type:,
         | 
| 91 | 
            +
                        name:,
         | 
| 92 | 
            +
                        description:,
         | 
| 93 | 
            +
                        unit:,
         | 
| 94 | 
            +
                        value_type:
         | 
| 95 | 
            +
                      )
         | 
| 96 | 
            +
                    end
         | 
| 97 | 
            +
             | 
| 98 | 
            +
                    def with_additional_attributes(_additional_attributes)
         | 
| 99 | 
            +
                      self
         | 
| 100 | 
            +
                    end
         | 
| 101 | 
            +
                  end
         | 
| 102 | 
            +
             | 
| 103 | 
            +
                  class NullMetric < Temporalio::Metric
         | 
| 104 | 
            +
                    attr_reader :metric_type, :name, :description, :unit, :value_type
         | 
| 105 | 
            +
             | 
| 106 | 
            +
                    def initialize(metric_type:, name:, description:, unit:, value_type:) # rubocop:disable Lint/MissingSuper
         | 
| 107 | 
            +
                      @metric_type = metric_type
         | 
| 108 | 
            +
                      @name = name
         | 
| 109 | 
            +
                      @description = description
         | 
| 110 | 
            +
                      @unit = unit
         | 
| 111 | 
            +
                      @value_type = value_type
         | 
| 112 | 
            +
                    end
         | 
| 113 | 
            +
             | 
| 114 | 
            +
                    def record(value, additional_attributes: nil); end
         | 
| 115 | 
            +
             | 
| 116 | 
            +
                    def with_additional_attributes(_additional_attributes)
         | 
| 117 | 
            +
                      self
         | 
| 118 | 
            +
                    end
         | 
| 119 | 
            +
                  end
         | 
| 120 | 
            +
                end
         | 
| 121 | 
            +
              end
         | 
| 122 | 
            +
            end
         | 
| @@ -5,26 +5,82 @@ require 'temporalio/api' | |
| 5 5 | 
             
            module Temporalio
         | 
| 6 6 | 
             
              module Internal
         | 
| 7 7 | 
             
                module ProtoUtils
         | 
| 8 | 
            -
                  def self.seconds_to_duration( | 
| 9 | 
            -
                    return nil if  | 
| 8 | 
            +
                  def self.seconds_to_duration(seconds_numeric)
         | 
| 9 | 
            +
                    return nil if seconds_numeric.nil?
         | 
| 10 10 |  | 
| 11 | 
            -
                    seconds =  | 
| 12 | 
            -
                    nanos = (( | 
| 11 | 
            +
                    seconds = seconds_numeric.to_i
         | 
| 12 | 
            +
                    nanos = ((seconds_numeric - seconds) * 1_000_000_000).round
         | 
| 13 13 | 
             
                    Google::Protobuf::Duration.new(seconds:, nanos:)
         | 
| 14 14 | 
             
                  end
         | 
| 15 15 |  | 
| 16 | 
            +
                  def self.duration_to_seconds(duration)
         | 
| 17 | 
            +
                    return nil if duration.nil?
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                    # This logic was corrected for timestamp at
         | 
| 20 | 
            +
                    # https://github.com/protocolbuffers/protobuf/pull/2482 but not for
         | 
| 21 | 
            +
                    # duration, so 4.56 is not properly represented in to_f, it becomes
         | 
| 22 | 
            +
                    # 4.5600000000000005.
         | 
| 23 | 
            +
                    (duration.seconds + duration.nanos.quo(1_000_000_000)).to_f
         | 
| 24 | 
            +
                  end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                  def self.time_to_timestamp(time)
         | 
| 27 | 
            +
                    return nil if time.nil?
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                    Google::Protobuf::Timestamp.from_time(time)
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                  def self.timestamp_to_time(timestamp)
         | 
| 33 | 
            +
                    return nil if timestamp.nil?
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                    # The regular to_time on the timestamp converts to local timezone,
         | 
| 36 | 
            +
                    # and we prefer not to make a separate .utc call (converts to local
         | 
| 37 | 
            +
                    # then back to UTC unnecessarily)
         | 
| 38 | 
            +
                    Time.at(timestamp.seconds, timestamp.nanos, :nanosecond, in: 'UTC')
         | 
| 39 | 
            +
                  end
         | 
| 40 | 
            +
             | 
| 16 41 | 
             
                  def self.memo_to_proto(hash, converter)
         | 
| 17 | 
            -
                    return nil if hash.nil?
         | 
| 42 | 
            +
                    return nil if hash.nil? || hash.empty?
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                    Api::Common::V1::Memo.new(fields: memo_to_proto_hash(hash, converter))
         | 
| 45 | 
            +
                  end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                  def self.memo_to_proto_hash(hash, converter)
         | 
| 48 | 
            +
                    return nil if hash.nil? || hash.empty?
         | 
| 18 49 |  | 
| 19 | 
            -
                     | 
| 50 | 
            +
                    hash.transform_keys(&:to_s).transform_values { |val| converter.to_payload(val) }
         | 
| 20 51 | 
             
                  end
         | 
| 21 52 |  | 
| 22 53 | 
             
                  def self.memo_from_proto(memo, converter)
         | 
| 23 | 
            -
                    return nil if memo.nil?
         | 
| 54 | 
            +
                    return nil if memo.nil? || memo.fields.size.zero? # rubocop:disable Style/ZeroLengthPredicate Google Maps don't have empty
         | 
| 24 55 |  | 
| 25 56 | 
             
                    memo.fields.each_with_object({}) { |(key, val), h| h[key] = converter.from_payload(val) } # rubocop:disable Style/HashTransformValues
         | 
| 26 57 | 
             
                  end
         | 
| 27 58 |  | 
| 59 | 
            +
                  def self.headers_to_proto(headers, converter)
         | 
| 60 | 
            +
                    return nil if headers.nil? || headers.empty?
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                    Api::Common::V1::Header.new(fields: headers_to_proto_hash(headers, converter))
         | 
| 63 | 
            +
                  end
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                  def self.headers_to_proto_hash(headers, converter)
         | 
| 66 | 
            +
                    return nil if headers.nil? || headers.empty?
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                    headers.transform_values { |val| converter.to_payload(val) }
         | 
| 69 | 
            +
                  end
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                  def self.headers_from_proto(headers, converter)
         | 
| 72 | 
            +
                    headers_from_proto_map(headers&.fields, converter)
         | 
| 73 | 
            +
                  end
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                  def self.headers_from_proto_map(headers, converter)
         | 
| 76 | 
            +
                    return nil if headers.nil? || headers.size.zero? # rubocop:disable Style/ZeroLengthPredicate Google Maps don't have empty
         | 
| 77 | 
            +
             | 
| 78 | 
            +
                    headers.each_with_object({}) do |(key, val), h| # rubocop:disable Style/HashTransformValues
         | 
| 79 | 
            +
                      # @type var h: Hash[String, Object?]
         | 
| 80 | 
            +
                      h[key] = converter.from_payload(val)
         | 
| 81 | 
            +
                    end
         | 
| 82 | 
            +
                  end
         | 
| 83 | 
            +
             | 
| 28 84 | 
             
                  def self.string_or(str, default = nil)
         | 
| 29 85 | 
             
                    str && !str.empty? ? str : default
         | 
| 30 86 | 
             
                  end
         | 
| @@ -49,6 +105,29 @@ module Temporalio | |
| 49 105 |  | 
| 50 106 | 
             
                    converter.to_payloads(values).payloads.to_ary
         | 
| 51 107 | 
             
                  end
         | 
| 108 | 
            +
             | 
| 109 | 
            +
                  class LazyMemo
         | 
| 110 | 
            +
                    def initialize(raw_memo, converter)
         | 
| 111 | 
            +
                      @raw_memo = raw_memo
         | 
| 112 | 
            +
                      @converter = converter
         | 
| 113 | 
            +
                    end
         | 
| 114 | 
            +
             | 
| 115 | 
            +
                    def get
         | 
| 116 | 
            +
                      @memo = ProtoUtils.memo_from_proto(@raw_memo, @converter) unless defined?(@memo)
         | 
| 117 | 
            +
                      @memo
         | 
| 118 | 
            +
                    end
         | 
| 119 | 
            +
                  end
         | 
| 120 | 
            +
             | 
| 121 | 
            +
                  class LazySearchAttributes
         | 
| 122 | 
            +
                    def initialize(raw_search_attributes)
         | 
| 123 | 
            +
                      @raw_search_attributes = raw_search_attributes
         | 
| 124 | 
            +
                    end
         | 
| 125 | 
            +
             | 
| 126 | 
            +
                    def get
         | 
| 127 | 
            +
                      @search_attributes = SearchAttributes._from_proto(@raw_search_attributes) unless defined?(@search_attributes)
         | 
| 128 | 
            +
                      @search_attributes
         | 
| 129 | 
            +
                    end
         | 
| 130 | 
            +
                  end
         | 
| 52 131 | 
             
                end
         | 
| 53 132 | 
             
              end
         | 
| 54 133 | 
             
            end
         | 
| @@ -3,6 +3,7 @@ | |
| 3 3 | 
             
            require 'temporalio/activity'
         | 
| 4 4 | 
             
            require 'temporalio/activity/definition'
         | 
| 5 5 | 
             
            require 'temporalio/cancellation'
         | 
| 6 | 
            +
            require 'temporalio/converters/raw_value'
         | 
| 6 7 | 
             
            require 'temporalio/internal/bridge/api'
         | 
| 7 8 | 
             
            require 'temporalio/internal/proto_utils'
         | 
| 8 9 | 
             
            require 'temporalio/scoped_logger'
         | 
| @@ -11,14 +12,17 @@ require 'temporalio/worker/interceptor' | |
| 11 12 | 
             
            module Temporalio
         | 
| 12 13 | 
             
              module Internal
         | 
| 13 14 | 
             
                module Worker
         | 
| 15 | 
            +
                  # Worker for handling activity tasks. Upon overarching worker shutdown, {wait_all_complete} should be used to wait
         | 
| 16 | 
            +
                  # for the activities to complete.
         | 
| 14 17 | 
             
                  class ActivityWorker
         | 
| 15 18 | 
             
                    LOG_TASKS = false
         | 
| 16 19 |  | 
| 17 20 | 
             
                    attr_reader :worker, :bridge_worker
         | 
| 18 21 |  | 
| 19 | 
            -
                    def initialize(worker | 
| 22 | 
            +
                    def initialize(worker:, bridge_worker:)
         | 
| 20 23 | 
             
                      @worker = worker
         | 
| 21 24 | 
             
                      @bridge_worker = bridge_worker
         | 
| 25 | 
            +
                      @runtime_metric_meter = worker.options.client.connection.options.runtime.metric_meter
         | 
| 22 26 |  | 
| 23 27 | 
             
                      # Create shared logger that gives scoped activity details
         | 
| 24 28 | 
             
                      @scoped_logger = ScopedLogger.new(@worker.options.logger)
         | 
| @@ -26,12 +30,13 @@ module Temporalio | |
| 26 30 | 
             
                        Activity::Context.current_or_nil&._scoped_logger_info
         | 
| 27 31 | 
             
                      }
         | 
| 28 32 |  | 
| 29 | 
            -
                      # Build up activity hash by name, failing if any fail validation
         | 
| 33 | 
            +
                      # Build up activity hash by name (can be nil for dynamic), failing if any fail validation
         | 
| 30 34 | 
             
                      @activities = worker.options.activities.each_with_object({}) do |act, hash|
         | 
| 31 35 | 
             
                        # Class means create each time, instance means just call, definition
         | 
| 32 36 | 
             
                        # does nothing special
         | 
| 33 | 
            -
                        defn = Activity::Definition.from_activity(act)
         | 
| 37 | 
            +
                        defn = Activity::Definition::Info.from_activity(act)
         | 
| 34 38 | 
             
                        # Confirm name not in use
         | 
| 39 | 
            +
                        raise ArgumentError, 'Only one dynamic activity allowed' if !defn.name && hash.key?(defn.name)
         | 
| 35 40 | 
             
                        raise ArgumentError, "Multiple activities named #{defn.name}" if hash.key?(defn.name)
         | 
| 36 41 |  | 
| 37 42 | 
             
                        # Confirm executor is a known executor and let it initialize
         | 
| @@ -88,8 +93,8 @@ module Temporalio | |
| 88 93 | 
             
                    def handle_start_task(task_token, start)
         | 
| 89 94 | 
             
                      set_running_activity(task_token, nil)
         | 
| 90 95 |  | 
| 91 | 
            -
                      # Find activity definition
         | 
| 92 | 
            -
                      defn = @activities[start.activity_type]
         | 
| 96 | 
            +
                      # Find activity definition, falling back to dynamic if present
         | 
| 97 | 
            +
                      defn = @activities[start.activity_type] || @activities[nil]
         | 
| 93 98 | 
             
                      if defn.nil?
         | 
| 94 99 | 
             
                        raise Error::ApplicationError.new(
         | 
| 95 100 | 
             
                          "Activity #{start.activity_type} for workflow #{start.workflow_execution.workflow_id} " \
         | 
| @@ -158,17 +163,19 @@ module Temporalio | |
| 158 163 | 
             
                        activity_id: start.activity_id,
         | 
| 159 164 | 
             
                        activity_type: start.activity_type,
         | 
| 160 165 | 
             
                        attempt: start.attempt,
         | 
| 161 | 
            -
                        current_attempt_scheduled_time:  | 
| 166 | 
            +
                        current_attempt_scheduled_time: Internal::ProtoUtils.timestamp_to_time(
         | 
| 167 | 
            +
                          start.current_attempt_scheduled_time
         | 
| 168 | 
            +
                        ) || raise, # Never nil
         | 
| 162 169 | 
             
                        heartbeat_details: ProtoUtils.convert_from_payload_array(
         | 
| 163 170 | 
             
                          @worker.options.client.data_converter,
         | 
| 164 171 | 
             
                          start.heartbeat_details.to_ary
         | 
| 165 172 | 
             
                        ),
         | 
| 166 | 
            -
                        heartbeat_timeout: start.heartbeat_timeout | 
| 173 | 
            +
                        heartbeat_timeout: Internal::ProtoUtils.duration_to_seconds(start.heartbeat_timeout),
         | 
| 167 174 | 
             
                        local?: start.is_local,
         | 
| 168 | 
            -
                        schedule_to_close_timeout: start.schedule_to_close_timeout | 
| 169 | 
            -
                        scheduled_time: start.scheduled_time | 
| 170 | 
            -
                        start_to_close_timeout: start.start_to_close_timeout | 
| 171 | 
            -
                        started_time: start.started_time | 
| 175 | 
            +
                        schedule_to_close_timeout: Internal::ProtoUtils.duration_to_seconds(start.schedule_to_close_timeout),
         | 
| 176 | 
            +
                        scheduled_time: Internal::ProtoUtils.timestamp_to_time(start.scheduled_time) || raise, # Never nil
         | 
| 177 | 
            +
                        start_to_close_timeout: Internal::ProtoUtils.duration_to_seconds(start.start_to_close_timeout),
         | 
| 178 | 
            +
                        started_time: Internal::ProtoUtils.timestamp_to_time(start.started_time) || raise, # Never nil
         | 
| 172 179 | 
             
                        task_queue: @worker.options.task_queue,
         | 
| 173 180 | 
             
                        task_token:,
         | 
| 174 181 | 
             
                        workflow_id: start.workflow_execution.workflow_id,
         | 
| @@ -178,13 +185,18 @@ module Temporalio | |
| 178 185 | 
             
                      ).freeze
         | 
| 179 186 |  | 
| 180 187 | 
             
                      # Build input
         | 
| 181 | 
            -
                      input = Temporalio::Worker::Interceptor:: | 
| 188 | 
            +
                      input = Temporalio::Worker::Interceptor::Activity::ExecuteInput.new(
         | 
| 182 189 | 
             
                        proc: defn.proc,
         | 
| 183 | 
            -
                         | 
| 184 | 
            -
             | 
| 185 | 
            -
             | 
| 186 | 
            -
             | 
| 187 | 
            -
             | 
| 190 | 
            +
                        # If the activity wants raw_args, we only decode we don't convert
         | 
| 191 | 
            +
                        args: if defn.raw_args
         | 
| 192 | 
            +
                                payloads = start.input.to_ary
         | 
| 193 | 
            +
                                codec = @worker.options.client.data_converter.payload_codec
         | 
| 194 | 
            +
                                payloads = codec.decode(payloads) if codec
         | 
| 195 | 
            +
                                payloads.map { |p| Temporalio::Converters::RawValue.new(p) }
         | 
| 196 | 
            +
                              else
         | 
| 197 | 
            +
                                ProtoUtils.convert_from_payload_array(@worker.options.client.data_converter, start.input.to_ary)
         | 
| 198 | 
            +
                              end,
         | 
| 199 | 
            +
                        headers: ProtoUtils.headers_from_proto_map(start.header_fields, @worker.options.client.data_converter) || {}
         | 
| 188 200 | 
             
                      )
         | 
| 189 201 |  | 
| 190 202 | 
             
                      # Run
         | 
| @@ -193,7 +205,8 @@ module Temporalio | |
| 193 205 | 
             
                        cancellation: Cancellation.new,
         | 
| 194 206 | 
             
                        worker_shutdown_cancellation: @worker._worker_shutdown_cancellation,
         | 
| 195 207 | 
             
                        payload_converter: @worker.options.client.data_converter.payload_converter,
         | 
| 196 | 
            -
                        logger: @scoped_logger
         | 
| 208 | 
            +
                        logger: @scoped_logger,
         | 
| 209 | 
            +
                        runtime_metric_meter: @runtime_metric_meter
         | 
| 197 210 | 
             
                      )
         | 
| 198 211 | 
             
                      Activity::Context._current_executor&.set_activity_context(defn, activity)
         | 
| 199 212 | 
             
                      set_running_activity(task_token, activity)
         | 
| @@ -226,9 +239,9 @@ module Temporalio | |
| 226 239 | 
             
                    def run_activity(activity, input)
         | 
| 227 240 | 
             
                      result = begin
         | 
| 228 241 | 
             
                        # Build impl with interceptors
         | 
| 229 | 
            -
                        # @type var impl: Temporalio::Worker::Interceptor:: | 
| 242 | 
            +
                        # @type var impl: Temporalio::Worker::Interceptor::Activity::Inbound
         | 
| 230 243 | 
             
                        impl = InboundImplementation.new(self)
         | 
| 231 | 
            -
                        impl = @worker. | 
| 244 | 
            +
                        impl = @worker._activity_interceptors.reverse_each.reduce(impl) do |acc, int|
         | 
| 232 245 | 
             
                          int.intercept_activity(acc)
         | 
| 233 246 | 
             
                        end
         | 
| 234 247 | 
             
                        impl.init(OutboundImplementation.new(self))
         | 
| @@ -287,13 +300,15 @@ module Temporalio | |
| 287 300 | 
             
                        cancellation:,
         | 
| 288 301 | 
             
                        worker_shutdown_cancellation:,
         | 
| 289 302 | 
             
                        payload_converter:,
         | 
| 290 | 
            -
                        logger | 
| 303 | 
            +
                        logger:,
         | 
| 304 | 
            +
                        runtime_metric_meter:
         | 
| 291 305 | 
             
                      )
         | 
| 292 306 | 
             
                        @info = info
         | 
| 293 307 | 
             
                        @cancellation = cancellation
         | 
| 294 308 | 
             
                        @worker_shutdown_cancellation = worker_shutdown_cancellation
         | 
| 295 309 | 
             
                        @payload_converter = payload_converter
         | 
| 296 310 | 
             
                        @logger = logger
         | 
| 311 | 
            +
                        @runtime_metric_meter = runtime_metric_meter
         | 
| 297 312 | 
             
                        @_outbound_impl = nil
         | 
| 298 313 | 
             
                        @_server_requested_cancel = false
         | 
| 299 314 | 
             
                      end
         | 
| @@ -301,11 +316,24 @@ module Temporalio | |
| 301 316 | 
             
                      def heartbeat(*details)
         | 
| 302 317 | 
             
                        raise 'Implementation not set yet' if _outbound_impl.nil?
         | 
| 303 318 |  | 
| 304 | 
            -
                         | 
| 319 | 
            +
                        # No-op if local
         | 
| 320 | 
            +
                        return if info.local?
         | 
| 321 | 
            +
             | 
| 322 | 
            +
                        _outbound_impl.heartbeat(Temporalio::Worker::Interceptor::Activity::HeartbeatInput.new(details:))
         | 
| 323 | 
            +
                      end
         | 
| 324 | 
            +
             | 
| 325 | 
            +
                      def metric_meter
         | 
| 326 | 
            +
                        @metric_meter ||= @runtime_metric_meter.with_additional_attributes(
         | 
| 327 | 
            +
                          {
         | 
| 328 | 
            +
                            namespace: info.workflow_namespace,
         | 
| 329 | 
            +
                            task_queue: info.task_queue,
         | 
| 330 | 
            +
                            activity_type: info.activity_type
         | 
| 331 | 
            +
                          }
         | 
| 332 | 
            +
                        )
         | 
| 305 333 | 
             
                      end
         | 
| 306 334 | 
             
                    end
         | 
| 307 335 |  | 
| 308 | 
            -
                    class InboundImplementation < Temporalio::Worker::Interceptor:: | 
| 336 | 
            +
                    class InboundImplementation < Temporalio::Worker::Interceptor::Activity::Inbound
         | 
| 309 337 | 
             
                      def initialize(worker)
         | 
| 310 338 | 
             
                        super(nil) # steep:ignore
         | 
| 311 339 | 
             
                        @worker = worker
         | 
| @@ -323,7 +351,7 @@ module Temporalio | |
| 323 351 | 
             
                      end
         | 
| 324 352 | 
             
                    end
         | 
| 325 353 |  | 
| 326 | 
            -
                    class OutboundImplementation < Temporalio::Worker::Interceptor:: | 
| 354 | 
            +
                    class OutboundImplementation < Temporalio::Worker::Interceptor::Activity::Outbound
         | 
| 327 355 | 
             
                      def initialize(worker)
         | 
| 328 356 | 
             
                        super(nil) # steep:ignore
         | 
| 329 357 | 
             
                        @worker = worker
         | 
| @@ -6,6 +6,8 @@ require 'temporalio/internal/bridge/worker' | |
| 6 6 | 
             
            module Temporalio
         | 
| 7 7 | 
             
              module Internal
         | 
| 8 8 | 
             
                module Worker
         | 
| 9 | 
            +
                  # Primary worker (re)actor-style event handler. This handles multiple workers, receiving events from the bridge,
         | 
| 10 | 
            +
                  # and handling a user block.
         | 
| 9 11 | 
             
                  class MultiRunner
         | 
| 10 12 | 
             
                    def initialize(workers:, shutdown_signals:)
         | 
| 11 13 | 
             
                      @workers = workers
         | 
| @@ -47,6 +49,16 @@ module Temporalio | |
| 47 49 | 
             
                                         end
         | 
| 48 50 | 
             
                    end
         | 
| 49 51 |  | 
| 52 | 
            +
                    def apply_workflow_activation_decoded(workflow_worker:, activation:)
         | 
| 53 | 
            +
                      @queue.push(Event::WorkflowActivationDecoded.new(workflow_worker:, activation:))
         | 
| 54 | 
            +
                    end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                    def apply_workflow_activation_complete(workflow_worker:, activation_completion:, encoded:)
         | 
| 57 | 
            +
                      @queue.push(Event::WorkflowActivationComplete.new(
         | 
| 58 | 
            +
                                    workflow_worker:, activation_completion:, encoded:, completion_complete_queue: @queue
         | 
| 59 | 
            +
                                  ))
         | 
| 60 | 
            +
                    end
         | 
| 61 | 
            +
             | 
| 50 62 | 
             
                    def raise_in_thread_or_fiber_block(error)
         | 
| 51 63 | 
             
                      @thread_or_fiber&.raise(error)
         | 
| 52 64 | 
             
                    end
         | 
| @@ -80,22 +92,25 @@ module Temporalio | |
| 80 92 | 
             
                      # * [worker index, :activity/:workflow, error] - poll fail
         | 
| 81 93 | 
             
                      # * [worker index, :activity/:workflow, nil] - worker shutdown
         | 
| 82 94 | 
             
                      # * [nil, nil, nil] - all pollers done
         | 
| 95 | 
            +
                      # * [-1, run_id_string, error_or_nil] - workflow activation completion complete
         | 
| 83 96 | 
             
                      result = @queue.pop
         | 
| 84 97 | 
             
                      if result.is_a?(Event)
         | 
| 85 98 | 
             
                        result
         | 
| 86 99 | 
             
                      else
         | 
| 87 | 
            -
                         | 
| 88 | 
            -
                        if  | 
| 100 | 
            +
                        first, second, third = result
         | 
| 101 | 
            +
                        if first.nil? || second.nil?
         | 
| 89 102 | 
             
                          Event::AllPollersShutDown.instance
         | 
| 103 | 
            +
                        elsif first == -1
         | 
| 104 | 
            +
                          Event::WorkflowActivationCompletionComplete.new(run_id: second, error: third)
         | 
| 90 105 | 
             
                        else
         | 
| 91 | 
            -
                          worker = @workers[ | 
| 92 | 
            -
                          case  | 
| 106 | 
            +
                          worker = @workers[first]
         | 
| 107 | 
            +
                          case third
         | 
| 93 108 | 
             
                          when nil
         | 
| 94 | 
            -
                            Event::PollerShutDown.new(worker:, worker_type:)
         | 
| 109 | 
            +
                            Event::PollerShutDown.new(worker:, worker_type: second)
         | 
| 95 110 | 
             
                          when Exception
         | 
| 96 | 
            -
                            Event::PollFailure.new(worker:, worker_type | 
| 111 | 
            +
                            Event::PollFailure.new(worker:, worker_type: second, error: third)
         | 
| 97 112 | 
             
                          else
         | 
| 98 | 
            -
                            Event::PollSuccess.new(worker:, worker_type | 
| 113 | 
            +
                            Event::PollSuccess.new(worker:, worker_type: second, bytes: third)
         | 
| 99 114 | 
             
                          end
         | 
| 100 115 | 
             
                        end
         | 
| 101 116 | 
             
                      end
         | 
| @@ -122,6 +137,35 @@ module Temporalio | |
| 122 137 | 
             
                        end
         | 
| 123 138 | 
             
                      end
         | 
| 124 139 |  | 
| 140 | 
            +
                      class WorkflowActivationDecoded < Event
         | 
| 141 | 
            +
                        attr_reader :workflow_worker, :activation
         | 
| 142 | 
            +
             | 
| 143 | 
            +
                        def initialize(workflow_worker:, activation:) # rubocop:disable Lint/MissingSuper
         | 
| 144 | 
            +
                          @workflow_worker = workflow_worker
         | 
| 145 | 
            +
                          @activation = activation
         | 
| 146 | 
            +
                        end
         | 
| 147 | 
            +
                      end
         | 
| 148 | 
            +
             | 
| 149 | 
            +
                      class WorkflowActivationComplete < Event
         | 
| 150 | 
            +
                        attr_reader :workflow_worker, :activation_completion, :encoded, :completion_complete_queue
         | 
| 151 | 
            +
             | 
| 152 | 
            +
                        def initialize(workflow_worker:, activation_completion:, encoded:, completion_complete_queue:) # rubocop:disable Lint/MissingSuper
         | 
| 153 | 
            +
                          @workflow_worker = workflow_worker
         | 
| 154 | 
            +
                          @activation_completion = activation_completion
         | 
| 155 | 
            +
                          @encoded = encoded
         | 
| 156 | 
            +
                          @completion_complete_queue = completion_complete_queue
         | 
| 157 | 
            +
                        end
         | 
| 158 | 
            +
                      end
         | 
| 159 | 
            +
             | 
| 160 | 
            +
                      class WorkflowActivationCompletionComplete < Event
         | 
| 161 | 
            +
                        attr_reader :run_id, :error
         | 
| 162 | 
            +
             | 
| 163 | 
            +
                        def initialize(run_id:, error:) # rubocop:disable Lint/MissingSuper
         | 
| 164 | 
            +
                          @run_id = run_id
         | 
| 165 | 
            +
                          @error = error
         | 
| 166 | 
            +
                        end
         | 
| 167 | 
            +
                      end
         | 
| 168 | 
            +
             | 
| 125 169 | 
             
                      class PollerShutDown < Event
         | 
| 126 170 | 
             
                        attr_reader :worker, :worker_type
         | 
| 127 171 |  | 
| @@ -0,0 +1,54 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'temporalio/cancellation'
         | 
| 4 | 
            +
            require 'temporalio/workflow'
         | 
| 5 | 
            +
            require 'temporalio/workflow/child_workflow_handle'
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            module Temporalio
         | 
| 8 | 
            +
              module Internal
         | 
| 9 | 
            +
                module Worker
         | 
| 10 | 
            +
                  class WorkflowInstance
         | 
| 11 | 
            +
                    # Implementation of the child workflow handle.
         | 
| 12 | 
            +
                    class ChildWorkflowHandle < Workflow::ChildWorkflowHandle
         | 
| 13 | 
            +
                      attr_reader :id, :first_execution_run_id
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                      def initialize(id:, first_execution_run_id:, instance:, cancellation:, cancel_callback_key:) # rubocop:disable Lint/MissingSuper
         | 
| 16 | 
            +
                        @id = id
         | 
| 17 | 
            +
                        @first_execution_run_id = first_execution_run_id
         | 
| 18 | 
            +
                        @instance = instance
         | 
| 19 | 
            +
                        @cancellation = cancellation
         | 
| 20 | 
            +
                        @cancel_callback_key = cancel_callback_key
         | 
| 21 | 
            +
                        @resolution = nil
         | 
| 22 | 
            +
                      end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                      def result
         | 
| 25 | 
            +
                        # Notice that we actually provide a detached cancellation here instead of defaulting to workflow
         | 
| 26 | 
            +
                        # cancellation because we don't want workflow cancellation (or a user-provided cancellation to this result
         | 
| 27 | 
            +
                        # call) to be able to interrupt waiting on a child that may be processing the cancellation.
         | 
| 28 | 
            +
                        Workflow.wait_condition(cancellation: Cancellation.new) { @resolution }
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                        case @resolution.status
         | 
| 31 | 
            +
                        when :completed
         | 
| 32 | 
            +
                          @instance.payload_converter.from_payload(@resolution.completed.result)
         | 
| 33 | 
            +
                        when :failed
         | 
| 34 | 
            +
                          raise @instance.failure_converter.from_failure(@resolution.failed.failure, @instance.payload_converter)
         | 
| 35 | 
            +
                        when :cancelled
         | 
| 36 | 
            +
                          raise @instance.failure_converter.from_failure(@resolution.cancelled.failure, @instance.payload_converter)
         | 
| 37 | 
            +
                        else
         | 
| 38 | 
            +
                          raise "Unrecognized resolution status: #{@resolution.status}"
         | 
| 39 | 
            +
                        end
         | 
| 40 | 
            +
                      end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                      def _resolve(resolution)
         | 
| 43 | 
            +
                        @cancellation.remove_cancel_callback(@cancel_callback_key)
         | 
| 44 | 
            +
                        @resolution = resolution
         | 
| 45 | 
            +
                      end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                      def signal(signal, *args, cancellation: Workflow.cancellation)
         | 
| 48 | 
            +
                        @instance.context._signal_child_workflow(id:, signal:, args:, cancellation:)
         | 
| 49 | 
            +
                      end
         | 
| 50 | 
            +
                    end
         | 
| 51 | 
            +
                  end
         | 
| 52 | 
            +
                end
         | 
| 53 | 
            +
              end
         | 
| 54 | 
            +
            end
         |