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



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

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, hints:) ⇒ Object



99
100
101
102
103
# File 'lib/temporalio/internal/proto_utils.rb', line 99

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

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

.convert_to_payload_array(converter, values, hints:) ⇒ Object



105
106
107
108
109
# File 'lib/temporalio/internal/proto_utils.rb', line 105

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

  converter.to_payloads(values, hints:).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



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

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



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

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

.headers_from_proto(headers, converter) ⇒ Object



73
74
75
# File 'lib/temporalio/internal/proto_utils.rb', line 73

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

.headers_from_proto_map(headers, converter) ⇒ Object



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

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

  # @type var h: Hash[String, Object?]
  h = {}
  headers.each { |key, val| h[key] = converter.from_payload(val) }
  h
end

.headers_to_proto(headers, converter) ⇒ Object



61
62
63
64
65
# File 'lib/temporalio/internal/proto_utils.rb', line 61

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



67
68
69
70
71
# File 'lib/temporalio/internal/proto_utils.rb', line 67

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
58
59
# 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

  h = {}
  memo.fields.each { |key, val| h[key] = converter.from_payload(val) }
  h
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)


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

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



86
87
88
# File 'lib/temporalio/internal/proto_utils.rb', line 86

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



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

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