sdk-java icon indicating copy to clipboard operation
sdk-java copied to clipboard

Split PayloadCodec into two Encoder/Decoder interfaces and have a separate config for each

Open ddavidyuk opened this issue 3 years ago • 0 comments

Is your feature request related to a problem? Please describe. There are multiple microservices, each one using a different encoding scheme for outgoing Temporal payloads, e.g.: Microservice A: binary/gzip Microservice B: binary/encrypt

Each microservice hosts its own activities and workflows that invoke each other.

Describe the solution you'd like We should be able to configure Java SDK on Microservice A to encode payloads using binary/gzip but decode the incoming payloads using either binary/gzip or binary/encrypt. Same for Microservice B (but use binary/encrypt for encoding).

Here are some code examples:

public interface PayloadEncoder {
    ByteString getEncoding();

    Payload encode(Payload payload) throws DataConverterException;
}

public interface PayloadDecoder {
    ByteString getEncoding();

    Payload decode(Payload payload) throws DataConverterException;

    default boolean willDecode(Payload payload) {
        ByteString encoding = payload.getMetadataOrDefault(EncodingKeys.METADATA_ENCODING_KEY, null);
        return getEncoding().equals(encoding);
    }
}

public class PayloadCodecs {
    final List<PayloadEncoder> encoders;
    final List<PayloadDecoder> decoders;

    public Payload encode(Payload payload) throws DataConverterException {
        Payload result = payload;
        for (PayloadEncoder encoder : encoders) {
            result = encoder.encode(result);
        }

        return result;
    }

    public Payload decode(Payload payload) throws DataConverterException {
        return decoders.stream().filter(decoder -> decoder.willDecode(payload))
                .findFirst()
                .map(decoder -> decode(decoder.decode(payload))) // !!! recursive call
                .orElse(payload);
    }
}

This can also be integrated into a Spring Boot module like this:

@Bean
// get all PayloadEncoder/Decoder beans, use all decoder beans for decoding (will be selected based on 
// the Payload's encoding header)
// use only select encoder beans for encoding
// example: temporal.payload-encoding=binary/encrypt,binary/gzip - first gzip the payload and then encrypt
public PayloadCodecs payloadCodecs(List<PayloadDecoder> decoders, 
List<PayloadEncoders> encoders, 
@Value("${temporal.payload-encoding}") List<String> encodings ) {
       return new PayloadCodecs(selectEncoders(encoders, encodings), decoders);
}

Describe alternatives you've considered Use our own library on top of Temporal Java SDK

Additional context Add any other context or screenshots about the feature request here.

ddavidyuk avatar Aug 31 '22 19:08 ddavidyuk