cloudstateio / cloudstate

Distributed State Management for Serverless
https://cloudstate.io
Apache License 2.0
763 stars 97 forks source link

Discussion: Action API #489

Open marcellanz opened 3 years ago

marcellanz commented 3 years ago

I'm working on the action entity support for Go. There are two aspects of the protocol and implementation that stand out in comparison to the other entity types I think. One minor difference is the naming of the Action service:

service ActionProtocol {}
service Crdt {}
service ValueEntity {}
service EventSourced {}

This is a minor thing, but I don't yet see why it has to be suffixed with Protocol.

Second, by reading the TCK and Action implementation, from a user API standpoint, the Action implementation doesn't use a context to emit side effects and choosing forwards or users service reply/responses. Differently to other entities, a io.cloudstate.javasupport.action.ActionReply is used to collect effects and choose a reply type (MessageReply, ForwardReply, FailureReply).

While the API is oriented towards the language implementing the action protocol and to be idiomatic, I'm curious if we tend or like to change the use of context objects in cloudstate APIs or like to use vehicles like the ActionReply to carry a protocols semantics. I assume we like to have where possible similar API experience for users. WDYT?

pvlugter commented 3 years ago

This is a minor thing, but I don't yet see why it has to be suffixed with Protocol.

There was a comment in the renaming (#442). This was just to avoid clashes with Action itself. So while there's Crdt (protocol) and CrdtEntity (thing), EventSourced (protocol) and EventSourcedEntity (thing), it was ending up as Action (protocol) and Action (thing). I think it would be useful to have a {StateModel}Protocol or similar convention for all of them. We'll likely rename Crdt protocol with the Replicated Entity rename.

Second, by reading the TCK and Action implementation, from a user API standpoint, the Action implementation doesn't use a context to emit side effects and choosing forwards or users service reply/responses.

Yes, the Action user API for java support is different. Not sure why. I'll let @jroper comment on this.

I think there's still more experimentation to do for different APIs in various language supports, so they may diverge for a while. I understand that similar APIs across languages would be simpler, while having idiomatic approaches should be prioritised. For Go support, if using context methods for Actions seems clearer and more consistent, I would go with that. I also think that the more functional APIs (returning the effects) are interesting to explore.

pvlugter commented 3 years ago

Since the ActionProtocol is mainly for Java support, while other languages can more easily distinguish or rename imports, another possibility could be to have the protocol service as Action and use the protobuf java options to generate a different name for the outer class. I can try things out.

marcellanz commented 3 years ago

Cool, thanks.

marcellanz commented 3 years ago

Yes, the Action user API for java support is different. Not sure why. I'll let @jroper comment on this.

WDYT @jroper?

jroper commented 3 years ago

The primary reason for this is to support a streaming approach - for unary actions it doesn't really matter, but for streamed actions, I wanted users to be able to return a stream, as opposed to the JS approach of imperative writes/effects/forwards on a context. So you can return a stream where each item in the stream is a forward, or an effect, or a reply, or a mixture of all of the above. If we didn't represent forwards/effects as a return value, and instead offered imperative methods to send them, then when streaming a mixture of forwards and replies, the forwards would be out of the stream context, and hence be able to overtake or lag behind the replies.

We could of course add methods to the context to imperatively forward/effect, but it would probably make sense to only include those in a unary out context.