Code Monkey home page Code Monkey logo

akkatecture's Introduction

nuget master dev code coverage chat who are we?
Nuget Package Build status Build status Coverage Come Chat we are reactive

Akkatecture

Akkatecture is a cqrs and event sourcing framework for dotnet core, build ontop of akka.net. Fully optimised around using akka's highly scalable message passing and event stream pub sub mechanisms. Akkatecture targets netstandard2.0.

Go ahead and take a look at our documentation, go over some concepts, and read the tips and tricks.

Features

  • Distributed: Each aggregate can operate concurrently in parallel inside of the actor system with isolated failure boundaries.
  • Message based: Making it highly scalable by being reactive from message passing, Akkatecture does not ask, it tells.
  • Event sourced: By design, aggregate roots derive their state by replaying persisted events.
  • Highly scalable: Work proceeds interactively and concurrently, overlapping in time, and may be done across nodes.
  • Configurable: Through akka.net's hocon configuration, you will be able to configure every aspect of your application.

Examples

Akkatecture comes with a few prescribed examples on how one might use it:

  • Simple: A simple console based example that shows the most simple example of how to create an aggregate and issue commands to it.

  • Walkthrough: Tutorial style sample based on the walkthrough in the Akkatecture documentation. The walkthrough proposes domain that should be modelled based on some business requirements. The walkthrough goes step by step covering all the primitives and features covered in Akkatecture to give you an understanding of the framework. The beginning of the walkthrough can be found here.

  • Cluster: A more involved sample that shows you how to do distributed aggregates using clustering. Read the readme for the sample for a good overview of the example.

  • Web: This sample shows how to integrate akka into an aspnet core project, specifically how to inject actor references when using akkatecture. Furthermore this project models a long running process that might be run behind a web application or something similar. Read the readme for more detailed information about the example.

  • Jobs: A simple sample that demonstrates how you would make a scheduled persistent job. Jobs are commands that can be persisted and scheduled to be executed at any arbitrary trigger point in time. Read the readme for more detailed information about the example. The documentation for this can be found here.

  • Tests: The test examples found in the Akkatecture.Test project is there to provide assistance when doing testing for Akkatecture. There is a simple domain modelled within the Akkatecture.TestHelpers project that includes a model of an aggregate with a simple aggregate saga, and these are used to do simple black box style testing on Akkatecture using akka.net's TestKit.

Note: This example is part of the Akkatecture simple example project, so checkout the code and give it a run.

//Create actor system
var system = ActorSystem.Create("useraccount-example");

//Create supervising aggregate manager for UserAccount aggregate root actors
var aggregateManager = system.ActorOf(Props.Create(() => new UserAccountAggregateManager()));

//Build create user account aggregate command with name "foo bar"
var aggregateId = UserAccountId.New;
var createUserAccountCommand = new CreateUserAccountCommand(aggregateId, "foo bar");

//Send command, this is equivalent to command.publish() in other cqrs frameworks
aggregateManager.Tell(createUserAccountCommand);

//tell the aggregateManager to change the name of the aggregate root to "foo bar baz"
var changeNameCommand = new UserAccountChangeNameCommand(aggregateId, "foo bar baz");
aggregateManager.Tell(changeNameCommand);

Assumptions About Akkatecture Developers

It would be ideal if you have some experience in domain driven design, cqrs, and event sourcing. It would also be beneficial for you to be familiar with actor systems, akka.net, and the extensibility points that akka gives you through hocon configuration. If you need to skill up on akka.net, check out petabridge's akka-bootcamp. If you are already familiar with akka.net, go through the walkthrough and you would have covered most of the concepts that this framework offers.

Status of Akkatecture

Akkatecture is still in development. The goal of this projects first version is to provide you with the neccassary building blocks to build out your own cqrs and event sourced application without having to think of the implementation details of akka.net coupled with CQRS and event sourcing. Right now Akkatecture is focussed on developing the story for projection rebuilding. Projection rebuilding is a crucial feature that will lend Akkatecture to a version 1.0.0 release.

Contributing

Code - If you want to contribute to the framework, do so on the dev branch and submit a PR.

Documentation - Akkatecture's documentation source is here, if you have any suggestions or improvements that can be made to them.

All contributions big or small are greatly appreciated!

Useful Resources

There are many different authoritative sources that prescribe best practices when building these kinds of systems that Akkatecture models. Here are a few articles and resources that can give you a good foundational grounding on the concepts used extensively in this project.

Domain-Driven Design

CQRS & Event sourcing

Eventual consistency

Video Content

Motivations

Doing domain driven design in a distributed scenario is quite tricky. And even more so when you add cqrs and event sourcing style mechanics to your business domain. Akka.net gives you powerful ways to co-ordinate and organise your business rules by using actors and message passing, which can be done by sending messages through location transparent addresses (or references). The major benefits of using akka.net is that we can isolate our domain models into actors where it makes sense, in Akkatecture's case, an actor = aggregate root, this design decision is done because actors are inherently consistent between message handles, which is very much the same as aggregate roots in domain driven design. There is a high impedance match when you impose the actor model onto domain driven design, because actors can only guarantee their own internal state's consistency just like aggregate roots which maintain their own consistency boundary. Modelling aggregates as actors in the actor model is highly congruent.

Akkatecture gives you a set of opinionated generic constructs that you can use to wire up your application so that you can focus on your main task, modelling and codifying your business domain.

Akka.net gives us a wealth of good APIs out of the box that can be used to build entire systems out of. It also has a decent ecosystem and community for support. Akkatecture is also of the opinion that commands translate well semantically in actor systems since telling commands is a form of message passing that fits well into the actor model paradigm.

Changelog

Akkatecture uses the methods of Keep A Changelog to keep track of features or functionality that has been added, changed, deprecated, removed, fixed, or patched for security reasons. The changelog also serves as a source of truth for the project's release notes.

Prerelease and Nightly Builds

Prerelease and nightly builds are not currently available. Please check back for updates soon from the maintainers at AfterLutz!

Prerelease feeds and nightly feeds (called alpha feeds in this project). Provide the most up to date packages for the project. Roughly speaking the prerelease feed is the most up to date packages that reflect master, and the nightly feed reflects the most up to packages derived from the dev branch. In other words, alpha feed is less stable than the prerelease feed but gets the features and fixes first. The access to the feeds:

Prerelease Feed - This is the Azure Artifacts URL, and this is the NuGet feed URL.

Nightly Feed - - This is the Azure Artifacts URL, and this is the NuGet feed URL.

Acknowledgements

  • Akka.NET - The project which AKkatecture builds ontop of, without akka.net, Akkatecture wouldnt exist.
  • EventFlow - Akkatecture has adapted the api surface from event flow to work in the akka actor world.
  • Nact - For giving us basis to write our documentation. Powered by gatsbyjs.

License

The MIT License (MIT)

Copyright (c) 2018 - 2021 Lutando Ngqakaza

https://github.com/AfterLutz/Akkatecture

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

akkatecture's People

Contributors

4deeptech avatar aaronontheweb avatar aman-mandal avatar briansain avatar cumpsd avatar dagilleland avatar damian-p avatar dependabot-preview[bot] avatar dependabot-support avatar dependabot[bot] avatar lutando avatar malclear avatar malclear-sh avatar siudeks avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

akkatecture's Issues

Code explanation request

This may be a big ask (you could consider me to be --less than-- a junior developer), but can anyone help me understand by explaining the code for the InitReceives() method in the DomainEventSubscriber base class?

It looks like maybe the method is converting the derived class Handle methods into Receive methods of the DomainEventSubscriber's base ReceiveActor class. I'm guessing its just using a lot of reflection to extract the method info from the Handle method and magic that method info into a Receive method.... but i'm not totally sure. The last foreach loops is confusing to me (because i don't really yet know anything about reflection), but i'm guessing that is the final conversation and creation step to actually make the final Receive methods ?

IExecutionResult should allow for returning a correlation value

Problem
When sending multiple commands, we are not able to correlate the IExecutionResult responses received from aggregate managers. This is not a problem when using a synchronous "Ask" from a UI application, but if several commands are sent from a single saga, for example, the responses can't be related to the requests (commands). We have to mitigate failures from within the saga such as by issuing compensating commands or retrying, but cannot.

Potential solution
An optional property, CorrelationId, should be added to IExecutionResult that will indicate which command succeeded or failed. I suggest an IIdentity type, with the expectation the user will return the Command object's ISourceId value.

I considered returning an object rather than IIdentity, but it might tempt users to query on the wrong side of the CQRS divide.

    public interface IExecutionResult
    {
        bool IsSuccess { get; } 
        IIdentity CorrelationId {get;}  // <-- new thing
    }

A solution exists, of course, in that we could create a custom implementation of this interface, but given that it's intended to be an asynchronous response to a request, it seems natural to indicate the request's identity with a correlation value.

AggregateRoot should allow for deleting Snapshot data

Problem: In my application, too many snapshot instances are being created for a given persistenceId. Data is being retained in the database which will never again be used. Currently, functionality exists for configuring the SaveSnapshot() function, but this only ever adds new snapshots. It does not cleanup the snapshots previously created. Old snapshots will not be used again (in my application).

Solution: The AggregateRoot class should be adjusted such that usage of either the DeleteSnapshot() or DeleteSnapshots() functions (from Akka.Persistence) can be configured. It is possible that some library users will want to use old snapshots in some manner, however. The new code should accommodate that desire by allowing for but not mandating that old snapshots be cleaned up.

Build system: need to push symbol packages to NuGet

Right now I don't think our current dotnet push command uploads the .snupkg files that contain debugging symbols for Akkatecture. These are needed in order to ensure that SourceLink et al all work properly.

Relevant area of build system:

- name: Build Packages
run: |
dotnet restore
dotnet build -c Release
dotnet pack -c Release --no-build /p:Version=${env:VERSION} --output ./bin/nuget
- name: Push Packages
working-directory: ./bin/nuget
run: dotnet nuget push "*.nupkg" -k "${{secrets.NUGET_API_KEY}}" -s https://api.nuget.org/v3/index.json --skip-duplicate

Incorporate the new Akka.Hosting into samples and base code

A new library, Akka.Hosting, is very helpful in configuring clustered Actor Systems. It reduces the hocon required.

Akka.Hosting should be incorporated into Akkatecture's sample and base code where applicable.

(More details to follow)

NuGet: need to rename all packages

In order to be published on NuGet we need to rename all of the Akkatecture NuGet packages.

I configured our NuGet publish key to look for AfterLutz.* paths, so that might be the easiest solution: just prepend AfterLutz. to the front of each project name.

Related: #34 (comment)

Racy Spec: Akkatecture.Tests.IntegrationTests.Aggregates.Sagas.AggregateSagaTests.SendingTest_FromTestAggregate_CompletesSaga

Version Information
Version of Akkatecture? current dev branch
Which Akkatecture Modules?

Describe the bug
Intermittent spec failure:

Akkatecture.Tests.IntegrationTests.Aggregates.Sagas.AggregateSagaTests.SendingTest_FromTestAggregate_CompletesSaga: Got a message of the expected type <Akkatecture.Aggregates.DomainEvent`3[[Akkatecture.TestHelpers.Aggregates.Sagas.Test.TestSaga, Akkatecture.TestHelpers, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null],[Akkatecture.TestHelpers.Aggregates.Sagas.Test.TestSagaId, Akkatecture.TestHelpers, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null],[Akkatecture.TestHelpers.Aggregates.Sagas.Test.Events.TestSagaTimeoutOccurred, Akkatecture.TestHelpers, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]]>. Also expected the predicate to return true but the message {TestSaga v4/TestSagaTimeoutOccurred:testSaga-test-a67d2252-d0ba-46aa-9138-6c18e9bba778} of type <Akkatecture.Aggregates.DomainEvent`3[[Akkatecture.TestHelpers.Aggregates.Sagas.Test.TestSaga, Akkatecture.TestHelpers, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null],[Akkatecture.TestHelpers.Aggregates.Sagas.Test.TestSagaId, Akkatecture.TestHelpers, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null],[Akkatecture.TestHelpers.Aggregates.Sagas.Test.Events.TestSagaTimeoutOccurred, Akkatecture.TestHelpers, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]]> did not match

To Reproduce
Not sure - it's intermittent, so would need to go through the test line by line to run it. Usually racy tests are a function of timings being too tightly coupled.

Expected behavior
Test should consistently pass.

Actual behavior
Intermittently fails.

Environment
Windows, .NET Core 3.1

Additional context
See an instance of it failing here: https://github.com/AfterLutz/Akkatecture/runs/4127994089?check_suite_focus=true - appears to have happened on Windows

Need to migrate MultiNodeTests

Version Information
Version of Akkatecture? current dev branch
Which Akkatecture Modules? https://github.com/AfterLutz/Akkatecture/tree/dev/test/Akkatecture.Tests.MultiNode

Describe the bug
Current implementation is using a hacky version of the old MNTR, whereas we ship native dotnet test support now: https://github.com/akkadotnet/Akka.MultiNodeTestRunner

Expected behavior
Should be able to run dotnet test on the entire solution, per what I did here: #12

Actual behavior
dotnet test barfs and dies because it depends on a custom entry point being executed.

Environment
Github Actions windows-latest and ubuntu-latest

Saga Timeout manager is not unique

Version Information
0.6,1

Describe the bug
Saga Timeout manager does not have a SagaId property and thats why its not unique.

To Reproduce
Steps to reproduce the behavior:

  1. Create a new Saga
  2. Add a handler for ISagaHandlesTimeout
  3. Instantiate a new saga. The first one works perfectly fine.
  4. Instantiate another saga - You will get this error message:
    ERR akka://your-app-system/user/yoursaga-saga] Actor name “BulkActionTimeout-timeoutmanager” is not unique!
    [akka://your-app-system/user/bulkaction-saga/bulkaction-a8ac291a-e157-4ba9-ac99-618d2831dee5#1018278655]: Akka.Actor.ActorInitializationException: Exception during creation
    ---> Akka.Actor.InvalidActorNameException: Actor name “BulkActionTimeout-timeoutmanager” is not unique!
    at Akka.Actor.Internal.NormalChildrenContainer.Reserve(String name)
    at Akka.Actor.ActorCell.ReserveChild(String name)
    at Akka.Actor.ActorCell.MakeChild(Props props, String name, Boolean async, Boolean systemService)
    at Akka.Actor.ActorCell.ActorOf(Props props, String name, Boolean isAsync, Boolean isSystemService)
    at Akka.Actor.ActorCell.ActorOf(Props props, String name)
    at Akkatecture.Sagas.AggregateSaga.AggregateSaga`3.PreStart()
    at Akka.Actor.ActorBase.AroundPreStart()
    at Akka.Persistence.Eventsourced.AroundPreStart()
    at Akka.Actor.ActorCell.<>c__DisplayClass176_0.b__0()
    at Akka.Actor.ActorCell.UseThreadContext(Action action)
    at Akka.Actor.ActorCell.Create(Exception failure)
    --- End of inner exception stack trace ---
    at Akka.Actor.ActorCell.Create(Exception failure)
    at Akka.Actor.ActorCell.FinishCreate()

Expected behavior
Multiple saga should. be able to handle timeouts uniquely

Actual behavior
Run time error

Screenshots

Environment
Linux

Additional context

Building the library using the build.cmd script fails

Version of Akkatecture?
Master
Which Akkatecture Modules?
Build system.
Describe the bug
A clear and concise description of what the bug is.
Building the library fils using the build.cmd script as it can't find the required files.
To Reproduce
Steps to reproduce the behavior:

  1. Go to 'the directory containing the build.cmd file.'
  2. Run this file from a command prompt.
  3. The build fails stating it can't find fake and/or the fake script.

Expected behavior
A clear and concise description of what you expected to happen.
The build is executed.
Actual behavior
What actually happened and how did it differ from your expectations?
The build cannot find the dependencies it requires to run.
Screenshots
If applicable, add screenshots to help explain your problem.

Environment
Are you running on Linux? Windows? Docker? Which version of .NET?
Windows with .net core 6.
Additional context
Add any other context about the problem here.

The build for the Documentation library is broken

Using either yarn install or npm install fails when attempting to build and run the Documentation repository locally.

The build ends with

fatal error: too many errors emitted, stopping now [-ferror-limit=]
2 warnings and 20 errors generated.
make: *** [Release/obj.target/sharp/src/common.o] Error 1
gyp ERR! build error
gyp ERR! stack Error: make failed with exit code: 2
gyp ERR! stack at ChildProcess.onExit (/usr/local/Cellar/node/17.0.1/libexec/lib/node_modules/npm/node_modules/node-gyp/lib/build.js:194:23)
gyp ERR! stack at ChildProcess.emit (node:events:390:28)
gyp ERR! stack at Process.ChildProcess._handle.onexit (node:internal/child_process:290:12)
gyp ERR! System Darwin 19.6.0
gyp ERR! command "/usr/local/Cellar/node/17.0.1/bin/node" "/usr/local/Cellar/node/17.0.1/libexec/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" "rebuild"
gyp ERR! cwd /Users/mlearner/work/afterlutz/Documentation/node_modules/sharp

To Reproduce
Steps to reproduce the behavior:

  1. Clone the repo found here: https://github.com/AfterLutz/Documentation
  2. Follow instructions on the ReadMe.md page

Need to create AfterLutz NuGet organization

Need to create an AfterLutz NuGet organization, invite 2-3 maintainers, and include one of the API Keys for publishing packages as a secret inside this repository so it can be used by CI.

Clustering should be able to accurately handle passivation/handoff(rebalance)

Version Information
Version of Akkatecture?
Akkatecture.Cluster

Describe the bug
The framework does not handle passivation and handoff messages well. The default behaviour for Akka.Net is to send a PosionPill during passivation/handoff (rebalance). Since there are layers to the aggregates/entities, the shard actor doesn't get notification of complete passivation/handoff which leads to an instable state.

Expected behavior
If a shard wants to passivate an idle entity or rebalance a shard, then the shard to be aware of when the process is completed on that aggregate(s).

Actual behavior
Aggregates are passivating, but the stashed state of the entity within the actor shard remains in the passivating state.

Environment
Docker

Artifacts should be published as "Akkatecture" instead of "Akkatecture.AL"

The artifacts in the last release were published as "Akkatecture.AL" as we, the administrators, did not have write access to the original "Akkatecture" NuGet packages. Now that we have acquired that access, we should publish to the original named account in NuGet.

Not doing so will break any existing users as the name of the assembly is baked into the default event serialization, in the Event Journal.

This will be a breaking change for users of "Akkatecture.AL". If help is required making the transition back to the original name, please reach out through Discord, or open an issue here.

The newer name "Akkatecture.AL" should be deprecated.

CI/CD: need to restore NuGet publish functionality

The current FAKE script has a lot of hard-coded defaults that point to Lutando's original repository and feeds. Need to change these to:

  1. Point to the AfterLutz NuGet organization's credentials, which can / should be stored as a secret in the repository so it can be accessed via Github Actions
  2. Publish a Github Release each time a tag is pushed, which is standard practice.

Behavior switching w/ Become() w/in the context of a DomainEventSubscriber

I am trying to build a draft form of a durable projection system for Akkatecture. I am wanting to use some of the concept of how the DomainEventSubscriber was built to do this. However, I would also like to be able to implement behavior switching (to enable a projector manager to 'play', 'pause' , 'stop' projectors and possibly other administrative functions.

Would it be possible to implement behavior switching with the way that the DomainEventSubscriber creates the Receive<> methods ? That is, I know that each Behavior (private void SomeBehavior() method ) has to have its own set of Receive<> methods to describe its behavior. How would I go about populating the Behavior methods with the Receive<> methods they need ? Would a call to a reflection based "CreateHandlers" method be needed at the top of each Behavior method be required ? For example, something like this ?

        private void Playing()
        {
            CreateHandlers();

            Command<PauseReactorCmd>(cmd =>
            {
                Become(Paused);
                Context.Parent.Tell(new PauseReactorAck());

            });

            Command<SomeOtherMsg>(cmd => {}); ...

        }

Build system: need to capture release NuGet packages in Github Release

- name: release
uses: actions/create-release@v1
id: create_release
with:
draft: false
prerelease: false
release_name: ${{ steps.version.outputs.version }}
tag_name: ${{ github.ref }}
body_path: CHANGELOG.md
env:
GITHUB_TOKEN: ${{ github.token }}
- we should modify this to capture all of the .nupkg and .snupkg output produced by dotnet pack for each release.

Durable Projections

I know that durable projections was something in the roadmap before everything was moved to /AfterLutz and it would be nice to see this on a roadmap now.

NuGet: need to update AfterLutz package metadata

There are a few areas of NuGet metadata that need to be updated so users of the .AL NuGet packages get the right information about the current status / home / maintainers of the project:

<Authors>Lutando Ngqakaza</Authors>
<Company>Lutando Ngqakaza</Company>
<Copyright>Copyright (c) Lutando Ngqakaza 2018 - 2020</Copyright>

<RepositoryUrl>https://github.com/Lutando/Akkatecture</RepositoryUrl>

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.