-
Notifications
You must be signed in to change notification settings - Fork 97
How to do CRUD #50
Comments
I think this would be a simplified API, but it would also encourage much larger message sizes (full entity/graph) which would have a negative impact on performance and storage requirements. |
@andyczerwonka That's not necessarily a problem, since snapshotting for event-sourced entities effectively also is the entire entity graph. Or rather, if that is a problem, then the problem is rather general for all state storage. |
@viktorklang agree, in the general case this CRUD story could be achieved purely by using a snapshot for every event. I maintain that, in practice, this could be a problem so I would encourage event sourcing, but for the simple case it'd work well in that it'd simplify the read case. |
@andyczerwonka Agreed, these tradeoffs need to be clearly documented. :) |
@viktorklang, What i did:
What i would like to do:
What are the next steps:
Any comments are welcome. |
@viktorklang, I would like to know if Cloudstate still wants to support CRUD. If it is the case I would also like to know at least one use case to address and which path we eventually want to go. I am evaluating doing CRUD on top of Event Sourcing (using the shopping cart example) and the only option I see now is based on Key Value. In this scenario the CRUD entity is a collection of key value. Perhaps there are another options and I would be happy to know about and to explore on them. I would be glad to have some feedback here :). |
@ralphlaude You definitely deserve some feedback here—it's just been crazy busy over here for a while. I'll try to sink some time into this PR tomorrow! :) (Thanks for working on this!!) |
@viktorklang don't worry everything is fine :), take your time. I just want to make sure things are going the right way. |
@viktorklang, in the context of CRUD we have the CRUD entity (having the entity_key) as aggregate with multiples sub-aggregates. We have some options to convey commands from the stateful function to the CRUD entity:
What should be the option to choose? Are there another options? |
for a CRUD entity we would like the command context to do operations like The existing command context for event sourced stateful function can be extend with those functionalities and it is the easy way to go. The other way to is to have a specific command context for CRUD entity with those functionalities. In this case we should know when to create each of them and for that we want to know which kind of event sourced entity we want to create. Here we have CRUD entity and EventSourced entity which are both EventSourced entity. This option could be more complicated because we have to make a difference between two differents EventSourced entity and we could eventually add a new kind of stateful service (CRUD stateful service) in the protocol. What do you think? Are there another options? |
@ralphlaude I think it would be expected to have |
@viktorklang, it makes sense and i will focus first on the protocol part. |
@viktorklang,
This is my proposal and any comments are welcome. It can be seen here:
|
Hi, |
@viktorklang, @pvlugter, @jroper, |
The progress can be seen here (master...ralphlaude:prototype-crud-on-event-sourcing) and is as follow:
The CRUD service in the java-support is right now initialized when a command come in. When the service starts there is not information upfront for initializing the CRUD service until a command is sent. I am wondering if there is another way to do the initialization upfront. Each command has a type so we know which service operation to route the command to.
Here is the content of the
|
@viktorklang, @jroper, @pvlugter here the appropriate PR - #220 |
I am not sure if it is better to define the types as an enum rather than a specific type of message. Usually enums are problematic in the evolution of proto files since any change to enum will break the parsers of older clients. |
@sleipnir thanks for the hints. i will change that to use dedicated type |
I'm not sure I understand the following:
For instance, how would you implement the ShoppingCart example using this CRUD protocol? |
@viktorklang,
The ShoppingCart don't have a
The protocol don't need the |
@ralphlaude TBH I don't think a service's external interface should need to disclose what type of state model it is using. For instance have a look at the CRDT example: https://github.com/cloudstateio/cloudstate/blob/master/protocols/example/crdts/crdt-example.proto Nothing in there tightly links the external interface to CRDTs. /cc @jroper @pvlugter @sleipnir @marcellanz Wdyt? |
@viktorklang, |
@ralphlaude Would it make sense to have |
I agree. Just remember that the user can link directly to what http operations he expects when annotating the proto file with http resources.
I think it makes more sense to map this in the method annotation. @ralphlaude what annotations are available to the user for CrudEntity? I think you can parameterize the type of invocation (get, save, delete, anything) as an annotation parameter, I think this is more fluent as it is similar to what developers are already used to when using web apis like spring mvc or jax -rs |
Especially since the main difference between an EventSourced and CRDT is the annotations used in the entities, to change this would be to break the symmetry of the APIs. |
I think the direction being taken here isn't quite right. This is back to front:
If the user function implements that, then we're saying the user function is the store, responsible for managing state. That's opposite of what Cloudstate is intending to achieve. If the proxy implements that, and then the user function invokes those calls back to the proxy, well that's closer to what Cloudstate is attempting to achieve, but it's also not the Cloudstate way of doing things - the user function isn't supposed to concern itself with retrieving state, that's meant to be the domain of the proxy. Here's what the protocol that I envision would look like:
This follows the same pattern as for event sourced and CRDT entities. Each CRUD entity is a single value that gets sharded across the Akka cluster, and when active, is stored in memory by the user function. When a command is received for a particular entity, if there's no active gRPC handle stream for that entity, a new stream is started, the value for the entity is looked up from the database, and then an init message is sent to the user function containing the value (or no value if not present in the db). Then the command is sent, and the user function can reply, optionally sending CRUD action, which can either update or delete the value from the database. After a period of inactivity, the entity will be shut down, just like for event sourced entities. |
@jroper your proposal for the Crud protocol is very clean 👍. |
James's design look nice, but begs the question of how do we really position Cloudstate. So far I was assuming that it is mostly a stateful scalable backend for serverless. |
@blublinsky Is that in fact what James is explaining is how he imagines or flow of events occurring and not an API for the end user. In the end user API, it is well built that you will notice a similarity as the usual CRUD model. |
@ralphlaude I believe that the same flow described by James for CRUD should be taken into account for KV support. ;) |
@blublinsky you can take a look here (#220) and every insights are welcome |
Will close this issue now. The initial PR in #220 is merged, and there are follow-up issues created:
|
Note that what is meant by CRUD is not SQL, or joins, but rather being able to get an Entity value, modifying it, and having the modified version stored for the next command/request. So "destructive updates".
Could in theory be implemented on top of the EventSourcing support by either storing the new Entity value as an event, or by repeatedly generating new Snapshots for each new state.
This also impacts the user-facing API as they would not have to deal with anything but the inbound commands (not events).
The text was updated successfully, but these errors were encountered: