Open wjglerum opened 4 years ago
I relate to this request because the business logic should speak the ubiquitous language
of the domain model
and not Avro
.
Here's my take on the potential solution:
AvroInlet
does indeed depend on SpecificRecordBase
But cloudflow
itself does not.
This can be seen looking around CodecInlet
and Codec
and see how the streamlets call Codec
So, there is no cloudflow
direct dependency on the SpecificRecordBase
This allows us to implement avro
<-> Scala serde using GenericRecord
s.
This article has a very nice approach using avro-hugger
, avro4s
and shapeless
, Coproduct
s and polymorphic function
s.
https://bitrock.it/blog/polymorphic-messages-in-kafka-streams.html
Avro doesn’t support inheritance between records, so any OOP strategy to have assets inherit properties from a common ancestor is unfortunately not viable.
@wjglerum @RayRoestenburg @michaelpnash please review and advise if this is agreeable.
Maybe we do not need expect cloudflow
main code base to handle this because support can be implemented externally, in cloudflow-contrib
for example.
We would like to use a polymorphic ADT as the message protocol between two Streamlets. Let's say for example I would like to design a
SubscriptionProtocol
with the following commands:SubscribeCmd
UnsubscribeCmd
And I would like to use this as the protocol between two Streamlets with Avro. We can tune
avrohugger
in ourbuild.sbt
to generate ADTs from Avro IDL files. See below with the following example protocol:And the following sbt configuration for our
datamodel
module:This will generate the following code for us (note: simplified)
However when we use this as the protocol in our Inlets and Outlets with our Streamlets it doesn't work:
So I was stuck on this approach.
Alternative approach
Next I took another approach where I would wrap different command inside a generic event. Which looks something like this:
This also fails to compile due to a limitiaton in the
avrohugger
plugin, as it can't generate aunion
with different records, only nullable fielts. Also support https://github.com/julianpeeters/avrohugger/issues/116 and below:We can fix this by using a
GenericRecordBase
, however theAvroInlets
andAvroOutlet
require a protocol which extendsSpecificRecordBase
. So we are stuck here too.Workaround
We now use a temporary workaround by defining option fields for each command:
This generates the following Scala code:
This works, but isn't pretty and not really extensible when we want to add more commands to this event.
Question
How could we support polymorphic ADTs in Cloudflow? Thanks!
Also see the discussion on [Gitter])https://gitter.im/lightbend/cloudflow?at=5e7ba8efaf5fed7748602ca8)