diff --git a/lib/temporal/configuration.rb b/lib/temporal/configuration.rb index 99e582a2..b93c9dbb 100644 --- a/lib/temporal/configuration.rb +++ b/lib/temporal/configuration.rb @@ -3,6 +3,7 @@ require 'temporal/connection/converter/payload/nil' require 'temporal/connection/converter/payload/bytes' require 'temporal/connection/converter/payload/json' +require 'temporal/connection/converter/payload/proto_json' require 'temporal/connection/converter/composite' module Temporal @@ -39,6 +40,7 @@ class Configuration payload_converters: [ Temporal::Connection::Converter::Payload::Nil.new, Temporal::Connection::Converter::Payload::Bytes.new, + Temporal::Connection::Converter::Payload::ProtoJSON.new, Temporal::Connection::Converter::Payload::JSON.new, ] ).freeze diff --git a/lib/temporal/connection/converter/payload/proto_json.rb b/lib/temporal/connection/converter/payload/proto_json.rb new file mode 100644 index 00000000..994c1e24 --- /dev/null +++ b/lib/temporal/connection/converter/payload/proto_json.rb @@ -0,0 +1,35 @@ +require 'temporal/json' + +module Temporal + module Connection + module Converter + module Payload + class ProtoJSON + ENCODING = 'json/protobuf'.freeze + + def encoding + ENCODING + end + + def from_payload(payload) + # TODO: Add error handling. + message_type = payload.metadata['messageType'] + descriptor = Google::Protobuf::DescriptorPool.generated_pool.lookup(message_type) + descriptor.msgclass.decode_json(payload.data) + end + + def to_payload(data) + return unless data.is_a?(Google::Protobuf::MessageExts) + Temporal::Api::Common::V1::Payload.new( + metadata: { + 'encoding' => ENCODING, + 'messageType' => data.class.descriptor.name, + }, + data: data.to_json, + ) + end + end + end + end + end +end diff --git a/spec/unit/lib/temporal/connection/converter/payload/proto_json_spec.rb b/spec/unit/lib/temporal/connection/converter/payload/proto_json_spec.rb new file mode 100644 index 00000000..5570d9df --- /dev/null +++ b/spec/unit/lib/temporal/connection/converter/payload/proto_json_spec.rb @@ -0,0 +1,25 @@ +require 'temporal/connection/converter/payload/proto_json' + +describe Temporal::Connection::Converter::Payload::ProtoJSON do + subject { described_class.new } + + describe 'round trip' do + it 'converts' do + # Temporal::Api::Common::V1::Payload is a protobuf. + # Using it as the "input" here to show the roundtrip. + # #to_payload will return a wrapped Payload around this one. + input = Temporal::Api::Common::V1::Payload.new( + metadata: { 'hello' => 'world' }, + data: 'hello world', + ) + + expect(subject.from_payload(subject.to_payload(input))).to eq(input) + end + end + + it 'skips if not proto message' do + input = { hello: 'world' } + + expect(subject.to_payload(input)).to be nil + end +end