Giter VIP home page Giter VIP logo

Comments (12)

pawelkaczor avatar pawelkaczor commented on May 29, 2024 1

@idoshamun You might find https://github.com/pawelkaczor/akka-ddd interesting as well.

from fun-cqrs.

pjan avatar pjan commented on May 29, 2024

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 Actions, but inject a Behaviour as configuration for our Aggregates that contain onCommand and onEvent methods. We can just define these objects plain and simple, yet in reality, we do this with Free and Interpreters 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.

octonato avatar octonato commented on May 29, 2024

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 a G[_]

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.

pjan avatar pjan commented on May 29, 2024

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 AggregateRefs. 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 ClassTags during construction of the AggregateRoot to do runtime checks. This works so far on the level of the Ids, yet not on the level of the Commands yet (the single TODO comment line in there at the moment). We'll definitely try to adopt the idea of AggregateRefs

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 🇧🇪 . Typing this from 🇯🇵

from fun-cqrs.

octonato avatar octonato commented on May 29, 2024

Thanks for all this. I will certainly investigate.

ps: I'm 🇧🇷 , but I live in 🇧🇪 .
When you are around you should come once to our meetup (www.bescala.org).

from fun-cqrs.

pjan avatar pjan commented on May 29, 2024

I'm in 🇧🇪 early November, but pretty much at the other side of the country. An FP in Scala study group isn't super tempting for me to cross the Brussels Ring, especially not during Holidays.

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.

octonato avatar octonato commented on May 29, 2024

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.

idoshamun avatar idoshamun commented on May 29, 2024

Any news to share about this?

from fun-cqrs.

octonato avatar octonato commented on May 29, 2024

@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.

idoshamun avatar idoshamun commented on May 29, 2024

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.

pjan avatar pjan commented on May 29, 2024

@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.

idoshamun avatar idoshamun commented on May 29, 2024

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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.