Comments (12)
@idoshamun You might find https://github.com/pawelkaczor/akka-ddd interesting as well.
from fun-cqrs.
Hi @rcavalcanti,
I just discovered your library. I/We've been using akka-(persistence)
heavily in my dayjob to work with persistent & distributed aggregate entities. Our internal library has evolved over the past year+, and now has striking resemblances with what you guys have here with fun-cqrs
. Differences are:
- it's only for akka (no other backends)
- we don't use the concept of
Action
s, but inject aBehaviour
as configuration for our Aggregates that containonCommand
andonEvent
methods. We can just define these objects plain and simple, yet in reality, we do this withFree
andInterpreters
to whatever Monad/Context we want, which helps us a lot for testing. I believe in the end it's similar to the actions DSL you have, but as we use Free, no need for us to reinvent the wheel - having the freedom to define our interpreters, also allows us to inject context and dependencies in a clean way
- we have no stable abstractions over view generation/event projections (read side) at this moment (only very rough ones). Currently we're still discovering new uses and use cases on a daily basis, so a little bit too early to see the patterns clearly in how to handle this.
We solved the issue you describe in exactly the same way as how it is described by James, and that has been working for us. In order to have it work with akka-cluster
, we just shard
the 'AggregateManager's.
from fun-cqrs.
Hi @pjan,
Cool to see that others are adopting more or less the same approach of having the aggregate Behavior as a separated abstraction.
Is this the project your are mentioning?
https://github.com/pjan/akka-ddd
I will have a look into it. May give me some inspirations.
Concerning your point about Free
. The reason we are not using it is that Actions
support different effects (Future, Try, Identity) and since #63 any effect you want.
Moreover, we don't chain computations in CQRS. One command, one transaction, one or more events. So, no need to create a structure and interpret it in a foldMap
.
Basically, the Interpreters
in Fun.CQRS should be seen as follows:
- given a Behavior that can produce any
F[_]
(ie: Future, Try, Identity, etc) - and given a backend that produces
G[_]
(ie: Future in case of AkkaBackend) - the Interpreter must be able to transform any
F[_]
into aG[_]
Therefore Free
didn't seem to be the right abstraction. That's why we only have interpreters.
I may have missed something about how Free
could be useful in that context. If you think I'm wrong, please let me know.
from fun-cqrs.
That project is rather old. It's where we started from 1.5 years ago, but lots of lessons learned in the meantime. Like I mentioned, the resemblance with fun-cqrs
in a lot of the abstractions we have now are striking, up to the point of using the abstract path-dependent types to make sure we can make an AggregateActor
accept any type of AggregateLike
, with its respective Protocol
.
The idea I absolutely love in your library, is the one of AggregateRef
s. In our case, we were always returning the bare ActorRef
and had no guarantees during compilation. We resorted to the ValidCommand
and InvalidCommand
patmat that you have as well, but play tricks with passing ClassTag
s during construction of the AggregateRoot
to do runtime checks. This works so far on the level of the Id
s, yet not on the level of the Command
s yet (the single TODO
comment line in there at the moment). We'll definitely try to adopt the idea of AggregateRef
s
Concerning Free
: I believe what you want would be possible using it, as well as using (a chain of) (implicit) FunctionK
/~>
s (which can map between kinds, e.g. Free[_]
~> Try[_]
andThen Try[_]
~> Future[_]
(of course, it all depends on the semantics and need of the application what type of interpreters you use)
A simple example from how this looks like (we're using cats
, and the UserAction
is a mini-language in the space of Users
)
type FE[A] = EitherT[Future, Throwable, A]
def apply(interpreter: UserAction ~> FE)(implicit Actions: UserAction.DSL[UserAction]): Behavior[User] = new Behavior[User] {
override def onCommand(state: AggregateState[User], cmd: Command)(implicit ec: ExecutionContext): Future[Either[Throwable, Events]] = {
val ops = for {
_ ← Actions.verifyCommand(state, cmd)
events ← Actions.generateEvents(state, cmd)
} yield events
(ops foldMap interpreter).value
}
override def onEvent(state: AggregateState[User], evt: Event): Either[Throwable, AggregateState[User]] =
{
val ops = Actions.applyEvent(state, evt)
Await.result((ops foldMap interpreter).value, 5.seconds)
}
}
(
What we particularly like about this, is that dependencies on repositories
, etc., as well as configuration can be injected only through the interpreter
(which in turn can be changed for e.g. tests)
The insight of abstracting over behaviour came early for us, as it allowed us to "easily" test whether that worked well without actually starting up actors. Using Free
now, we can also test behaviour with spawning actors, if we'd wanted to though.
Edit: Funny; just saw you're Belgian too
from fun-cqrs.
Thanks for all this. I will certainly investigate.
ps: I'm
When you are around you should come once to our meetup (www.bescala.org).
from fun-cqrs.
I'm in
I'll maybe try to clean up my code, (factor in the AggregateRef
idea at the same time), and put it up on gh so you can browse it.
from fun-cqrs.
You don't have to come for the FP study group. You can come along just to share your experience with CQRS/ES. ;-)
from fun-cqrs.
Any news to share about this?
from fun-cqrs.
@idoshamun, no progress so far. Current systems in prod are not being hit by this issue and I haven't find time to continue it.
Looking forward for help.
from fun-cqrs.
I have just started to investigate this whole CQRS / Event Sourcing architectures and bumped into your library. How come production systems don't need this feature? How do they distribute their service to more than one server without clustering support?
from fun-cqrs.
@idoshamun everything for this is implemented in akka-d3
and production battle tested. (including readside, as long as you use cassandra
that is – there's an interface for other backends if you need them, and implementation "should be straightforward").
If you tune your system well, with a sensible time to sleep for persistent actors, a single node can host a lot of entities before you need to resort to clustering (not taking availability requirements into account here, which changes everything).
from fun-cqrs.
My main concern actually is high availability right now, at least 2 nodes is mandatory for HA and without clustering you can't achieve consistency. I'll take a look at akka-d3
as well. Thanks :)
from fun-cqrs.
Related Issues (20)
- Support for Scala 2.13 HOT 1
- Removal of `handleCommandAsync`, `tryToHandleCommand` and `manyEvents` methods
- timeout for applyCommand HOT 4
- Eventhandling idempotency possibly flawed HOT 5
- Simplifying Command and Events
- AkkaBackend: Sender doesn't get any notification in case of empty list of Events
- Make the InMemoryBackend more flexible HOT 3
- Improve error message when Aggregate is not configured HOT 1
- Support for Scala 2.12
- Upgrade EventsSourceProvider to use akka.persistence.query.EventEnvelope2 in Akka 2.4 HOT 3
- Actor is not unique exception when configuring two backends in the same actor system. HOT 2
- Replace type projections by path dependent types
- Command and Event Handlers as PartialFunction HOT 1
- RxScala dependency for 2.11 HOT 7
- PersistedOffsetAkka mechanism inefficient HOT 6
- The EventsMonitorActor is hardcoded to timeout after 10 seconds
- AggregateActor "pipeTo self" bypasses termination logic of AggregateManager HOT 3
- Future of fun-cqrs HOT 5
- Multiple aggregates per actor system? HOT 4
- Would you be willing to accept a pull request for the Projection trait to have a additional method handler when event is successfully handled? HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from fun-cqrs.