Skip to content

Conversation

@calum-stripe
Copy link
Contributor

@calum-stripe calum-stripe commented Mar 21, 2023

Overview

Adds the payload codec pipeline described here https://docs.temporal.io/security#payload-codec.

This adds a new configuration option called payload_codec which always runs after the payload has been serialized (and before deserialization) when sent to (and received from) the server.

Currently, all payloads go through the data converter but only non search attributes payloads should go through payload codecs (otherwise if the payload is transformed into something the server can not read e.g. compressed or encrypted, then the server will reject it because it can not insert non datetime strings for example into the es index)

Test Plan

# unit test
bundle exec rspec spec/

# integration test
cd examples
(terminal 1) ./bin/worker
(terminal 2) USE_ENCRYPTION=1 ./bin/worker
(terminal 3) USE_ERROR_SERIALIZATION_V2=1 ./bin/worker
(terminal 4) bundle exec rspec spec/integration

nagl-stripe and others added 30 commits October 27, 2021 10:54
…nal-with-start

Change how signal_with_start is exposed
…nal-with-start

Update method signature in temporal test fixture
…nal-with-start

Update our FailWorkflowTask logic's call to ErrorHandler.handle
…ner/woflo-482

Workflow await condition in context wait_for
…ner/woflo-482-fix

Fix EventTarget comparison with wildcard
…ner/m1-fixes

Set Ruby 2.7 to be consistent with pay-server
…ins_schedule_to_start

Turn off schedule_to_start activity timeout by default
@bergundy
Copy link

In the official SDKs search attributes do not go through the user configurable data converter, might want to do the same here.

@calum-stripe
Copy link
Contributor Author

calum-stripe commented Mar 21, 2023

In the official SDKs search attributes do not go through the user configurable data converter, might want to do the same here.

this is true, I wonder if anyone has built a data converter for their search attributes though that by removing this and just using JSON would break their existing setup? Should we bump the version just incase? @bergundy

Copy link
Contributor

@jeffschoner-stripe jeffschoner-stripe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to update the existing encryption test to use this new pipeline? I think it's better suited to your solution rather than switching out the converter like it does today.


def from_search_attribute_payload(payload_map)
# skips the payload_codec step because search attributes don't use this pipeline
payload_map.map { |key, value| [key, payload_converter.from_payload(value)] }.to_h
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The abstraction is seeping through here a bit. Should this be named something like from_payload_map_without_codec? The call on search attributes would then be made outside of this file which is specific to performing various kinds of encoding.

Temporal.configuration.converter
end

def payload_codec
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A comment at the top of this file or on this method explaining the difference between payload converters and payload codecs would be worthwhile. Or actually probably in configuration.rb where a user would see it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added to the configuration.rb, let me know what you think

Comment on lines +6 to +20
def encodes(payloads)
return nil if payloads.nil?

Temporalio::Api::Common::V1::Payloads.new(
payloads: payloads.payloads.map(&method(:encode))
)
end

def decodes(payloads)
return nil if payloads.nil?

Temporalio::Api::Common::V1::Payloads.new(
payloads: payloads.payloads.map(&method(:decode))
)
end
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would these be overridden by someone extending this class? Why not move these into payloads.rb?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

they can be, I just was following the same pattern as in payloads.rb which seems to be define the same thing (from_payloads and to_payloads with logic then from_payload and to_payload are empty and required)

You probably are going to only override encode or decode but you have the option to override all for if the use case needs it.

payload_codec.encode(payload)
end

def to_search_attribute_payload(data)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same thing here in the other direction

# the codecs are applied last to first meaning the earlier encodings wrap the later ones.
# When decoding, the codecs are applied first to last to reverse the effect.
class Chain < Base
def initialize(payload_codecs:)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: This might be more ergonomic with a splat or non-keyword argument instead

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i agree, i was just keeping the same pattern as

def initialize(payload_converters:)
, what do you think?

@@ -0,0 +1,76 @@
require 'temporal/connection/converter/codec/chain'

describe Temporal::Connection::Converter::Codec::Base do
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Testing the base class seems strange to me since no one is expected to use this directly. It will always be extended, right? This might be a further indication that these non-abstract methods should simply be moved into payloads.rb instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm, i don't disagree, just was following the pattern that was already in place for from_payloads and to_payloads. What do you think? Im easy either way.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we do remove, ill remove the unit tests

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.