Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Durable State Entity (Value Entity) #30277

Closed
8 tasks done
patriknw opened this issue May 31, 2021 · 15 comments
Closed
8 tasks done

Durable State Entity (Value Entity) #30277

patriknw opened this issue May 31, 2021 · 15 comments
Assignees
Labels
3 - in progress Someone is working on this ticket t:persistence t:typed
Milestone

Comments

@patriknw
Copy link
Member

patriknw commented May 31, 2021

To reduce the conceptual complexity for new users or simple use cases we can have another type of persistent entity that stores the full state after processing each command instead of using event sourcing. The user API can be very simple, conceptually a function from current state and incoming command to next (stored) state.

(State, Command) => State

It would read the state from the database when the entity is started and thereafter holding it in memory. The returned state would be stored and the next command is not processed until the state is successfully stored (same semantics as EventSourcedBehavior).

Much of the surrounding parts would be the same, such as using Cluster Sharding for managing the entities. This is nice for the journey from value entities to event sourced entities.

The database specific implementations can be added to existing Akka Persistence plugin implementations, starting with the JDBC plugin. The plugin would serialize the state and store as a blob with the persistenceId as the primary key. In-place updates when the state is changed.

MVP tasks (may become issues):

  • User facing API (Java and Scala) and its implementation. The goal is to stay as close as possible to the EventSourcedBehavior API. Early spike experiment of the API: Durable State Behavior #29984
  • Extend akka-persistent plugin API for ValueEntityStore
  • In-memory implementation of ValueEntityStore and TestKit
  • Tests
  • ValueEntityStore implementation in akka-persistence-jdbc
  • ValueEntityStore implementation in akka-persistence-spanner (we already have most of it implemented there), see https://github.com/akka/akka-persistence-spanner/pull/145
  • Projection SourceProvider implementation for jdbc
  • Reference documentation.
@patriknw patriknw added 1 - triaged Tickets that are safe to pick up for contributing in terms of likeliness of being accepted t:persistence t:typed labels May 31, 2021
@ihostage
Copy link
Contributor

It will be great if the API of ValueEntityStore can be simply extended/reimplemented to store a typed data in many columns (JDBC for example) instead of the one BLOB column. I think that Projections for ValueEntity can again increase complexity that trying to reduce on this issue. But for the simple case (with full responsibility of actions), selecting some typed data from persistence storage (for simple reporting as an example) can be a great trade-off.

@patriknw
Copy link
Member Author

patriknw commented Jun 1, 2021

@ihostage Thanks for a great suggestion. That's something we have been thinking about, and the reason I didn't list it in the MVP tasks is that I wanted to keep the scope as small as possible. The door for that should be open.

A plugin may support custom DAO implementation to support queries on secondary indexes directly on the stored state table.

@patriknw
Copy link
Member Author

patriknw commented Jun 1, 2021

Regarding the name "Value Entity". It might be too confusing since it could be associated with Value Object in DDD, and Value vs Entity doesn't make sense.

The background is that the name comes from key-value entity. Perhaps we should spell it out KeyValueEntity? (KeyValueStore).

Since we already have EventSourcedBehavior we could also consider naming it KeyValueBehavior for consistency reasons .

@patriknw patriknw added 3 - in progress Someone is working on this ticket and removed 1 - triaged Tickets that are safe to pick up for contributing in terms of likeliness of being accepted labels Jun 1, 2021
patriknw added a commit that referenced this issue Jun 1, 2021
* name can be discussed, I used KeyValueBehavior so far because
  * KeyValue makes it less risk to confuse with Value Object in DDD
  * Behavior instead of Entity to be consistent with EventSourcedBehavior

* implementation is based on a copy of the EventSourcedBehavior and then
  refactoring all things that are not needed or different such as:
  * remove ReplayingEvents recovery phase
  * remove retention and snapshotting
  * remove SnapshotSelectionCriteria and snapshots
  * remove PersistAll
  * remove event handler, event types
  * rename EventSourced
  * single static tag
  * KeyValueAdapter
  * KeyValueSignal

* KeyValueStore plugin api with similar extension mechanism as query plugins
  * KeyValueStore, KeyValueUpdateStore
  * KeyValueStoreQuery

* note that the KeyValueStore can be pretty useful for other things also
patriknw added a commit that referenced this issue Jun 1, 2021
* name can be discussed, I used KeyValueBehavior so far because
  * KeyValue makes it less risk to confuse with Value Object in DDD
  * Behavior instead of Entity to be consistent with EventSourcedBehavior

* implementation is based on a copy of the EventSourcedBehavior and then
  refactoring all things that are not needed or different such as:
  * remove ReplayingEvents recovery phase
  * remove retention and snapshotting
  * remove SnapshotSelectionCriteria and snapshots
  * remove PersistAll
  * remove event handler, event types
  * rename EventSourced
  * single static tag
  * KeyValueAdapter
  * KeyValueSignal

* KeyValueStore plugin api with similar extension mechanism as query plugins
  * KeyValueStore, KeyValueUpdateStore
  * KeyValueStoreQuery

* note that the KeyValueStore can be pretty useful for other things also
patriknw added a commit that referenced this issue Jun 1, 2021
* name can be discussed, I used KeyValueBehavior so far because
  * KeyValue makes it less risk to confuse with Value Object in DDD
  * Behavior instead of Entity to be consistent with EventSourcedBehavior

* implementation is based on a copy of the EventSourcedBehavior and then
  refactoring all things that are not needed or different such as:
  * remove replicated event sourcing
  * remove ReplayingEvents recovery phase
  * remove retention and snapshotting
  * remove SnapshotSelectionCriteria and snapshots
  * remove PersistAll
  * remove event handler, event types
  * rename EventSourced
  * single static tag
  * KeyValueAdapter
  * KeyValueSignal

* KeyValueStore plugin api with similar extension mechanism as query plugins
  * KeyValueStore, KeyValueUpdateStore
  * KeyValueStoreQuery

* note that the KeyValueStore can be pretty useful for other things also
@ihostage
Copy link
Contributor

ihostage commented Jun 1, 2021

@patriknw

Regarding the name "Value Entity". It might be too confusing since it could be associated with Value Object in DDD, and Value vs Entity doesn't make sense.

I absolutely agree.

Since we already have EventSourcedBehavior we could also consider naming it KeyValueBehavior for consistency reasons

If EventSourcedBehavior is a behavior sourced by events, how about StateSourcedBehavior when the behavior will be sourced by (suddenly 😄 ) state? 🤔

@octonato
Copy link
Member

octonato commented Jun 2, 2021

I read EventSourcedBehavior as: the state that will be passed to this behavior is event sourced. Maybe not really what the English language will say though.

Following this, StateSourcedBehavior would mean the state that will be passed to this behavior is state sourced. That's weird, no?

And KeyValueBehavior is: the state that will be passed to this behavior is persisted in a key-value fashion.

I personally don't associate key-value automatically with persistence but rather with a Map. It could give the impression that the Actor is a sort of Map.

We previously played with the name DurableBehavior or DurableStateBehavior, but then, if we follow the reasoning above: the state that will be passed to this behavior is durable. That's sound fairly correct, but how exactly we make it durable? CRUD, KeyValue, EventSourced?

Now, do we really need to leak the persistence impl in the name? Does it really matter if it's CRUD or KeyValue? If we allow users to swap the store and persist it the way they want, would that still make sense to call it KeyValue?

That said, I still think that DurableStateBehavior is a better name and the default, most simple implementation, would be a KeyValue store.

@patriknw
Copy link
Member Author

patriknw commented Jun 2, 2021

My thinking about KeyValueBehavior wasn't so much about the key-value storage, even though that is also part of it.
The Key is the entityId and the Value is the state of the entity. It's durable because it's in the Akka Persistence module.

Another consideration we must take into account in the naming is that it's called Value Entity in Akka Serverless and it's somewhat of a failure if we can't align the name of what is conceptually the same thing between Akka Serverless and Akka.

I added Key to drive the attention away from DDD Value Object. Then changed Entity to Behavior to be consistent with existing naming in Akka.

That said, I'm not attached to KeyValueBehavior. I could accept DurableStateBehavior with the drawback that we don't align the naming with Akka Serverless. I would also be fine with using ValueEntity and describe in docs that it's not Value Object.

@sleipnir
Copy link

sleipnir commented Jun 2, 2021 via email

@ihostage
Copy link
Contributor

ihostage commented Jun 2, 2021

Another consideration we must take into account in the naming is that it's called Value Entity in Akka Serverless and it's somewhat of a failure if we can't align the name of what is conceptually the same thing between Akka Serverless and Akka.

I agree that correlation with naming in Akka Serverless makes sense. 🤔 I missed this point 😞

@johanandren
Copy link
Member

I think using Entity here is a bit confusing as it implies a higher level of abstraction, the actor will not become an entity until used together with sharding (akka.cluster.sharding.typed.(scaladsl|javadsl).Entity) and is addressed by id. It can still also be useful without combining with sharding to get durable state (non clustered, in a singleton, sharded daemon process etc).

ValueBehavior doesn't feel right though and I can't come up with another combination of Value and Behavior, I think DurableStateBehavior or something along those lines is the best I've seen so far.

Perhaps we can instead tie the ends together with docs, having a "Value Entity" doc section describing how to set the actor up with sharding?

@patriknw
Copy link
Member Author

patriknw commented Jun 3, 2021

@sleipnir I guess that discussion is cloudstateio/cloudstate#220 (comment)?

Thinking about it some more I think I anyway failed to align it with Akka Serverless when naming it KeyValueBehavior. It's not very close to ValueEntity. Maybe I'm overthinking that aspect. Might not be important and we can manage that by documentation, as Johan said.

I think we are back at DurableStateBehavior as the best alternative.

patriknw added a commit that referenced this issue Jun 3, 2021
* implementation is based on a copy of the EventSourcedBehavior and then
  refactoring all things that are not needed or different such as:
  * remove replicated event sourcing
  * remove ReplayingEvents recovery phase
  * remove retention and snapshotting
  * remove SnapshotSelectionCriteria and snapshots
  * remove PersistAll
  * remove event handler, event types
  * rename EventSourced
  * single static tag
  * DurableStateAdapter
  * DurableStateSignal

* DurableStateStore plugin api with similar extension mechanism as query plugins
  * DurableStateStore, DurableStateUpdateStore
  * DurableStateStoreQuery

* note that the DurableStateStore can be pretty useful for other things also
@sleipnir
Copy link

sleipnir commented Jun 3, 2021

@sleipnir I guess that discussion is cloudstateio/cloudstate#220 (comment)?

Yes!

Thinking about it some more I think I anyway failed to align it with Akka Serverless when naming it KeyValueBehavior. It's not very close to ValueEntity. Maybe I'm overthinking that aspect. Might not be important and we can manage that by documentation, as Johan said.

I think we are back at DurableStateBehavior as the best alternative.

I agree with you. ValueEntity never made sense to me, but I proposed that you look at the discussion to gather all the ideas that ever existed about this type of entity and name. Thanks for going there to look.

patriknw added a commit that referenced this issue Jun 3, 2021
First implementation of DurableStateBehavior, #30277
@patriknw patriknw changed the title Value Entity Durable State Entity (Value Entity) Jun 4, 2021
patriknw added a commit that referenced this issue Jun 7, 2021
fix default DurableStateStore pluginId and config, #30277
@He-Pin
Copy link
Member

He-Pin commented Jun 8, 2021

def upsertObject(persistenceId: String, seqNr: Long, value: A, tag: String)

Can a value have multi tags?

@patriknw
Copy link
Member Author

patriknw commented Jun 8, 2021

Can a value have multi tags?

I intentionally simplified that to only one tag for DurableStateStoreBehavior. I can't see a clear use case when that will be needed. For event sourced it can be used for defining sub-sets of events consumed by different eventsByTag consumers, but that doesn't make much sense for the full state changes.

@patriknw
Copy link
Member Author

patriknw commented Jul 1, 2021

@debasishg @RayRoestenburg I removed the testkit from the in initial scope. We already have an in-memory implementation that can be used. Full TestKit can be added later, and that is an excellent task for the community to contribute.

You find the existing Spanner implementation here: https://github.com/akka/akka-persistence-spanner/blob/master/journal/src/main/scala/akka/persistence/spanner/SpannerObjectStore.scala

When it comes to the reference docs I think it can follow the same structure as for event sourcing: https://doc.akka.io/docs/akka/current/typed/persistence.html

@ignasi35
Copy link
Contributor

I intentionally simplified that to only one tag for DurableStateStoreBehavior. I can't see a clear use case when that will be needed. For event sourced it can be used for defining sub-sets of events consumed by different eventsByTag consumers, but that doesn't make much sense for the full state changes.

It is true that since we're only storing state we have fewer data to query over. But it's only one fewer dimension. A Domain where users attached 3 tags to each Event would likely require 2 events per State, users lose the temporal aspect that event-sourcing provides but all other criteria to add tags over an entity remain, no?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
3 - in progress Someone is working on this ticket t:persistence t:typed
Projects
None yet
Development

No branches or pull requests

9 participants