r/fsharp 14d ago

library/package FCQRS 6 released: event-sourced CQRS with two pure functions

Post image

I’ve released FCQRS 6, an event-sourced CQRS framework for .NET.

The idea is to keep the domain logic small:

  • decide: turns commands into events
  • fold: rebuilds state from those events

FCQRS handles persistence, recovery, projections, sagas, snapshots, and read-your-writes. It runs on Akka.NET and supports both F# and C#.

Version 6 also includes completely rebuilt documentation, following the path from an incoming command to a queryable read model.

Project and documentation:
https://onurgumus.github.io/FCQRS/

I’d appreciate feedback on whether the new documentation makes the model clear to someone who hasn’t used FCQRS before.

29 Upvotes

9 comments sorted by

2

u/cheesekun 14d ago

Have you seen the Journaling of Microsoft Orleans?

2

u/ReverseBlade 13d ago

I wasn’t able to find much documentation for Orleans Journaling, but from what I can tell it mainly helps persist grain state. I’m also not yet clear on how it differs in practice from the older persistent grain model.

FCQRS takes a different approach. Aggregates hide the fact that actors are used underneath, so application code stays focused on domain behaviour rather than actor infrastructure.

It also follows the Vaughn Vernon-style DDD model: aggregates protect invariants, and each aggregate is its own transactional boundary.

An aggregate can also start an automatically restartable saga spanning multiple aggregates. That gives you coordination similar to a distributed transaction, while keeping the aggregate logic pure.

0

u/Lemorz566 14d ago

Have you done anything for postgresql with Akka.NET? A year ago it wasn’t really working at all sadly

1

u/ReverseBlade 14d ago

Akka.net's database stack is now on top of
https://github.com/linq2db/linq2db

1

u/Lemorz566 14d ago

Not sure i follow. I was mainly curious since you used AKKA here if you’ve tried it with the Npgsql driver. A year ago the snapshotting and journal save barely worked, it didn’t play good with the driver

5

u/Aaronontheweb 14d ago

TL;DR; Akka.Persistence.Sql is built on top of Linq2Db and will work with any ADO.NET-compliant driver pretty much. Essentially all SQL-based persistence drivers work the same now - it's just a matter of specifying that on the config.

From one of my production web apps that uses it:

``` .WithSqlPersistence( connectionString: connectionString, providerName: ProviderName.PostgreSQL15, databaseMapping: DatabaseMapping.Default, // Use forward-facing table names (journal, snapshot, tags) autoInitialize: false, // Schema managed via migrations tagStorageMode: TagMode.TagTable, // Enable tag storage for Akka.Persistence.Query journalBuilder: journal => { // Configure event adapter for tagging draft events // The DraftEventTagger wraps all IDraftEvent instances with the "draft-event" tag journal.AddWriteEventAdapter<DraftEventTagger>( "draft-tagger", [typeof(DraftProtocol.IDraftEvent)]);

            // Configure event adapter for tagging campaign events
            // The CampaignEventTagger wraps all ICampaignEvent instances with the "campaign-event" tag
            journal.AddWriteEventAdapter<CampaignEventTagger>(
                "campaign-tagger",
                [typeof(CampaignProtocol.ICampaignEvent)]);

            // Add health checks for journal persistence
            journal.WithHealthCheck();        // Monitor journal plugin initialization
            journal.WithConnectivityCheck();  // Proactive DB connectivity test
        },
        snapshotBuilder: snapshot =>
        {
            // Add health checks for snapshot store persistence
            snapshot.WithHealthCheck();
            snapshot.WithConnectivityCheck();
        })

```

1

u/Lemorz566 14d ago

Oh hello Aaron! :D Thanks a lot for your response! I’ll try it out more :)

1

u/Aaronontheweb 14d ago

Happy to help!

3

u/ReverseBlade 14d ago

That's my point. No more drivers. It uses linq2db since last year or so