Marlowe Runtime protocols versioning #337
paluh
started this conversation in
Architecture
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
The problem
marlowe-runtime
consists of many subservices which speak different protocols. Many components can be deployed and used separately so we should not assume that consistency can be reached through some single global supervisor. Additionally it seems that different strategies of development (like partially centralized workflows) proved to be useful but can be hard to work with when we update only parts of the runtime and want to sure that we are testing proper subservices with proper versions.Given the above set of circumstances it seems that quick detection of misconfiguration (different service than expected) or protocol version incoherence could be in general beneficial.
Scope
I want here to not only evaluate the proposal but also to clarify the status of ongoing prototypical implementation (we wanted to have it in place to simplify debugging / deployment etc.). Of course if we decide to change the approach or drop that idea I can remove relevant parts from the code base ;-)
References
cardano-node
In
cardano-node
we can find separate Handshake mini protocol (descrived here Shelley Networking Protocol - 3.6 Handshake mini protocol) and dedicated, enum like data type. It is worth to note that cardano node handles multiple versions of the protocol at the same time. Motivation and complexity of this feature is nicely summarized in The Cardano Consensus and Storage Layer - 6.2.1 Versioning):and
marlowe-runtime
In
marlowe-runtime
stack we had one handshake example implemented as a part ofChainSeek
meta protocol.In the codebase we have also pretty interesting attempt to autogenerate version tag based on the type structure with the help of Template Haskell. It is worth to point out that
SchemaVersion
which is part of chain seek versioning is related to the query schema not the "full protocol itself".Current status
newtype SchameVersion = SchemaVersion String
was replaced bynewtype SchemaVersion schema = SchemaVersion String
so we can use the type across many different protocols in type safe manner but share simple encoding and decoding. We mark currently "query schema" or "command schema" using this phantom.I've updated the
Template Haskell
accordingly to the above change. I also started experimenting withProtocolVersion
which reaches forMessage
type family instances likereifyInstances ''Message [protocolType] >>= [DataInstD _ _ _ _ constructor _] -> do
but I was forced to abandon that attempt because...Template Haskell created in general (either original or refactored one) somewhat unstable hashes - we hash a type info string representation which contains type variable identifiers (like
TyConI (..) [KindedTV status_6989586621679236658 StarT,KindedTV err_6989586621679236659 StarT,KindedTV result_6989586621679236660 StarT] Nothing [ForallC [KindedTV era_6341068275337885238 StarT] []...
). Even if we rewrite / reindex the type info AST structure it seems like a lot of work and a bit fragile strategy - the representation of the data type can probably differ a bit accross different GHC versions, var rewriting can be bug prone, protocol can change also because of the changes of message encoding which is not related to the message structure etc. I'm now switching to the manually provided versionsString
as a version tag.Because it would be nice to not only report protocol version inconsistency but also provide some more details to the user/developer about protocol itself. So I'm creating for version ids which also carry over the info about the protocol itself like
marlowe-tx-job-1
I've simplified for now the handshake logic - I assume that servers are able to handle a single and concrete version of the protocol. I did this because we are not really able now to fulfill multi version handling promise - we don't carry around the negotiated version to behave accordingly. We could pretend that in the context of
query
server we preserve backward compatibility of the past queries and responses but it seems really limiting as well at this point.I've already added the handshake step to the additional two protocols (
Query
andJob
) frommarlowe-protocols
and updated concrete protocols which relied on them. We still miss this step inMarlowe.Runtime.Protocol.Sync
andMarlowe.Runtime.Protocol.HeaderSync
frommarlowe-runtime
.Propositions and questions
The existing versioning approach doesn't provide quick feedback about protocol mismatch itself which could be easily analysed by the developer - we were getting only info about the hash/version mismatch. Can we make protocol name a required clearly separated field of the protocol - as first attempt I propose something simple like
newtype ProtocolVersion p = ProtocolVersion { protocolName :: String, version :: String }
.Do you think that this handshake addition is really worth keeping and extending? Should I migrate all other protocols and update all the state machine diagrams?
Beta Was this translation helpful? Give feedback.
All reactions