Module: Temporalio::Internal::ProtoUtils

Defined in:
lib/temporalio/internal/proto_utils.rb

Defined Under Namespace

Classes: LazyMemo, LazySearchAttributes

Class Method Summary collapse

Class Method Details

.assert_non_reserved_name(name) ⇒ Object



109
110
111
112
113
114
115
116
# File 'lib/temporalio/internal/proto_utils.rb', line 109

def self.assert_non_reserved_name(name)
  name = name&.to_s # In case it's a symbol or not present
  return unless name
  raise "'#{name}' cannot start with '__temporal_'" if name.start_with?('__temporal_')
  # Might as well disable __stack_trace and __enhanced_stack_trace everywhere even though technically it's only
  # reserved for queries
  raise "'#{name}' name invalid" if name == '__stack_trace' || name == '__enhanced_stack_trace'
end

.convert_from_payload_array(converter, payloads) ⇒ Object



97
98
99
100
101
# File 'lib/temporalio/internal/proto_utils.rb', line 97

def self.convert_from_payload_array(converter, payloads)
  return [] if payloads.empty?

  converter.from_payloads(Api::Common::V1::Payloads.new(payloads:))
end

.convert_to_payload_array(converter, values) ⇒ Object



103
104
105
106
107
# File 'lib/temporalio/internal/proto_utils.rb', line 103

def self.convert_to_payload_array(converter, values)
  return [] if values.empty?

  converter.to_payloads(values).payloads.to_ary
end

.duration_to_seconds(duration) ⇒ Object



16
17
18
19
20
21
22
23
24
# File 'lib/temporalio/internal/proto_utils.rb', line 16

def self.duration_to_seconds(duration)
  return nil if duration.nil?

  # This logic was corrected for timestamp at
  # https://github.com/protocolbuffers/protobuf/pull/2482 but not for
  # duration, so 4.56 is not properly represented in to_f, it becomes
  # 4.5600000000000005.
  (duration.seconds + duration.nanos.quo(1_000_000_000)).to_f
end

.enum_to_int(enum_mod, enum_val, zero_means_nil: false) ⇒ Object



88
89
90
91
92
93
94
95
# File 'lib/temporalio/internal/proto_utils.rb', line 88

def self.enum_to_int(enum_mod, enum_val, zero_means_nil: false)
  # Per https://protobuf.dev/reference/ruby/ruby-generated/#enum when
  # enums are read back, they are symbols if they are known or number
  # otherwise
  enum_val = enum_mod.resolve(enum_val) || raise('Unexpected missing symbol') if enum_val.is_a?(Symbol)
  enum_val = nil if zero_means_nil && enum_val.zero?
  enum_val
end

.from_user_metadata(metadata, converter) ⇒ Object



134
135
136
137
138
139
# File 'lib/temporalio/internal/proto_utils.rb', line 134

def self.(, converter)
  [
    (converter.from_payload(.summary) if &.summary), #: String?
    (converter.from_payload(.details) if &.details) #: String?
  ]
end

.headers_from_proto(headers, converter) ⇒ Object



71
72
73
# File 'lib/temporalio/internal/proto_utils.rb', line 71

def self.headers_from_proto(headers, converter)
  headers_from_proto_map(headers&.fields, converter)
end

.headers_from_proto_map(headers, converter) ⇒ Object



75
76
77
78
79
80
81
82
# File 'lib/temporalio/internal/proto_utils.rb', line 75

def self.headers_from_proto_map(headers, converter)
  return nil if headers.nil? || headers.size.zero? # rubocop:disable Style/ZeroLengthPredicate -- Google Maps don't have empty

  headers.each_with_object({}) do |(key, val), h| # rubocop:disable Style/HashTransformValues
    # @type var h: Hash[String, Object?]
    h[key] = converter.from_payload(val)
  end
end

.headers_to_proto(headers, converter) ⇒ Object



59
60
61
62
63
# File 'lib/temporalio/internal/proto_utils.rb', line 59

def self.headers_to_proto(headers, converter)
  return nil if headers.nil? || headers.empty?

  Api::Common::V1::Header.new(fields: headers_to_proto_hash(headers, converter))
end

.headers_to_proto_hash(headers, converter) ⇒ Object



65
66
67
68
69
# File 'lib/temporalio/internal/proto_utils.rb', line 65

def self.headers_to_proto_hash(headers, converter)
  return nil if headers.nil? || headers.empty?

  headers.transform_values { |val| converter.to_payload(val) }
end

.memo_from_proto(memo, converter) ⇒ Object



53
54
55
56
57
# File 'lib/temporalio/internal/proto_utils.rb', line 53

def self.memo_from_proto(memo, converter)
  return nil if memo.nil? || memo.fields.size.zero? # rubocop:disable Style/ZeroLengthPredicate -- Google Maps don't have empty

  memo.fields.each_with_object({}) { |(key, val), h| h[key] = converter.from_payload(val) } # rubocop:disable Style/HashTransformValues
end

.memo_to_proto(hash, converter) ⇒ Object



41
42
43
44
45
# File 'lib/temporalio/internal/proto_utils.rb', line 41

def self.memo_to_proto(hash, converter)
  return nil if hash.nil? || hash.empty?

  Api::Common::V1::Memo.new(fields: memo_to_proto_hash(hash, converter))
end

.memo_to_proto_hash(hash, converter) ⇒ Object



47
48
49
50
51
# File 'lib/temporalio/internal/proto_utils.rb', line 47

def self.memo_to_proto_hash(hash, converter)
  return nil if hash.nil? || hash.empty?

  hash.transform_keys(&:to_s).transform_values { |val| converter.to_payload(val) }
end

.reserved_name?(name) ⇒ Boolean

Returns:

  • (Boolean)


118
119
120
121
122
123
# File 'lib/temporalio/internal/proto_utils.rb', line 118

def self.reserved_name?(name)
  name = name&.to_s # In case it's a symbol or not present
  return false unless name

  name.start_with?('__temporal_') || name == '__stack_trace' || name == '__enhanced_stack_trace'
end

.seconds_to_duration(seconds_numeric) ⇒ Object



8
9
10
11
12
13
14
# File 'lib/temporalio/internal/proto_utils.rb', line 8

def self.seconds_to_duration(seconds_numeric)
  return nil if seconds_numeric.nil?

  seconds = seconds_numeric.to_i
  nanos = ((seconds_numeric - seconds) * 1_000_000_000).round
  Google::Protobuf::Duration.new(seconds:, nanos:)
end

.string_or(str, default = nil) ⇒ Object



84
85
86
# File 'lib/temporalio/internal/proto_utils.rb', line 84

def self.string_or(str, default = nil)
  str && !str.empty? ? str : default
end

.time_to_timestamp(time) ⇒ Object



26
27
28
29
30
# File 'lib/temporalio/internal/proto_utils.rb', line 26

def self.time_to_timestamp(time)
  return nil if time.nil?

  Google::Protobuf::Timestamp.from_time(time)
end

.timestamp_to_time(timestamp) ⇒ Object



32
33
34
35
36
37
38
39
# File 'lib/temporalio/internal/proto_utils.rb', line 32

def self.timestamp_to_time(timestamp)
  return nil if timestamp.nil?

  # The regular to_time on the timestamp converts to local timezone,
  # and we prefer not to make a separate .utc call (converts to local
  # then back to UTC unnecessarily)
  Time.at(timestamp.seconds, timestamp.nanos, :nanosecond, in: 'UTC')
end

.to_user_metadata(summary, details, converter) ⇒ Object



125
126
127
128
129
130
131
132
# File 'lib/temporalio/internal/proto_utils.rb', line 125

def self.(summary, details, converter)
  return nil if (!summary || summary.empty?) && (!details || details.empty?)

   = Temporalio::Api::Sdk::V1::UserMetadata.new
  .summary = converter.to_payload(summary) if summary && !summary.empty?
  .details = converter.to_payload(details) if details && !details.empty?
  
end