# Revo Framework documentation

Revo is a simple application framework for modern C#/.NET applications built with *event sourcing*, *CQRS* and *DDD*. It is released under the [MIT license](https://github.com/revoframework/Revo/blob/develop/LICENSE) and you can find its sources on [Github](https://github.com/revoframework/Revo).

This guide explains what this framework is, explains some of its fundamentals needed to get started with it and also serves as a basic reference guide. You can start by reading the [Overview](/general/overview) or by exploring an example application in [Getting started](/general/getting-started).

{% hint style="info" %}
Revo framework development is supported by company [**Olify IO s.r.o.**](https://olify.io/)
{% endhint %}


# Overview

Revo is an application framework for modern C#/.NET applications built with *event sourcing*, *CQRS* and *DDD*.

* [**Features**](/general/features)
* [**Super-short example**](/general/super-short-example)
* [**Design overview**](/general/overview/design-overview)
* [Project structure](/general/overview/project-structure)

## Requirements

The framework is written in the latest version of C# and primarily targets .NET Core 3.1+/.NET Standard 2.0.

Revo makes a heavy use of the C# async/await pattern and uses the TAP (Task Asynchronous Pattern) throughout its entire codebase (i.e. *async all the way* approach).


# Design overview

Following diagram depicts the typical data flows in Revo framework. This might give you a small insight into how the overall architecture of the framework looks.

![Data flows during a typical request processing in Revo.](/files/-LBzN52gBWJoy98xn3C1)

To learn more about the request processing in Revo, see [Request life-cycle](/reference-guide/request-life-cycle).


# Project structure

The framework codebase is split into a number of submodules, making it possible to only use what is needed.

* **Core**
  * **Revo.Core** Implements framework’s core features like events or commands and defines basic structures and interfaces for things like the unit of work pattern, security permissions and other utilities.
  * **Revo.DataAccess** Lower-level data access layer that provides interfaces and other abstractions for working with databases, independent of domain concepts (aggregates, consistency boundaries, etc.).
  * **Revo.Domain** Defines most of the framework’s building blocks for an application domain model – i.e. aggregates, entities, sagas, etc.
  * **Revo.Infrastructure** Interfaces for working with application domain and related aspects of an applications – e.g. aggregate repositories, event stores, projections, jobs, asynchronous event queues, etc.
  * **Revo.Testing** Provides several useful facilities for easier application testing – e.g. assertions for event-sourced aggregates or fake repositories (refer to the [Testing](/reference-guide/testing) chapter).
* **Providers**
  * **Revo.AspNetCore** Provides support for ASP.NET Core applications – application life cycle hooks, user context, authentication, etc.
  * **Revo.AspNet** Provides support for ASP.NET applications – application life cycle hooks, user context, authentication, etc.
  * **Revo.EasyNetQ** EasyNetQ integration for event messaging via RabbitMQ.
  * **Revo.EFCore**

    &#x20;Data access and infrastructure (aggregate store, event store, async events...) implementation using Entity Framework Core.
  * **Revo.EF6**

    &#x20;Data access and infrastructure (aggregate store, event store, async events...) implementation using Entity Framework 6.
  * **Revo.Hangfire** Hangfire integration for background jobs.
  * **Revo.Raven** Data access layer implementation using RavenDB database system.
  * **Revo.Rebus** Rebus integration for command/query and event messaging with RabbitMQ.
* **Extensions**
  * **Revo.Extensions.History**

    Change-tracking and entity history features.
  * **Revo.Extensions.Notifications** An extensive and customizable framework for user notifications (including mail notifications, push notifications, etc.).
* **Tests**
* **Examples**


# Features

The framework combines the concepts of event sourcing, CQRS and DDD to provide support for building applications that are scalable, maintainable, can work in distributed environments and are easy to integrate with outside world. As such, it takes some rather opinionated approaches on the design of certain parts of its architecture. Revo also offers other common features and infrastructure that is often necessary for building complete applications – for example, database migrations, event upgrades, authorizations, validations, messaging, integrations, multi-tenancy or testing. Furthermore, its extensions implement other useful features like entity history change-tracking, auditing or user notifications.

[**Domain-Driven Design**](/reference-guide/domain-building-blocks)\
Building blocks for rich DDD-style domain models ([aggregates](/reference-guide/domain-building-blocks#aggregates), [entities](/reference-guide/domain-building-blocks#entities), [value objects](/reference-guide/domain-building-blocks#value-objects), [domain events](/reference-guide/domain-building-blocks#domain-events), [repositories](/reference-guide/data-persistence#aggregate-repository)...)

.

[**Event Sourcing**](/reference-guide/events)\
Implementing event-sourced entity persistence with support for multiple event store backends (PostgreSQL, MSSQL, SQLite...).

[**CQRS**](/reference-guide/commands-and-queries)\
Segregating command and query responsibilities with:

* [Commands and queries  ](/reference-guide/commands-and-queries#commands-queries)
* Command/query [handlers  ](/reference-guide/commands-and-queries#command-query-handlers)
* Processing pipeline with filters for cross-cutting concerns ([authorization](/reference-guide/authorization), [validation](/reference-guide/validation), etc.)
* [Different read/write models](/reference-guide/projections)

[**A/synchronous event processing**](/reference-guide/events)\
Support for both [synchronous](/reference-guide/events#synchronous-event-processing) and [asynchronous](/reference-guide/events#asynchronous-event-processing) event processing, guaranteed *at-least-once* delivery, event queues with strict sequence ordering (optionally), event source catch-ups, optional [pseudo-synchronous event dispatch](/reference-guide/events#pseudo-synchronous-event-dispatch) for listeners (projectors, for example).

[**Data access**](/reference-guide/data-persistence)\
&#x20;Thin abstraction layer for easy data persistence (e.g. querying read models) using *Entity Framework Core*, *Entity Framework 6*, *RavenDB,* testable *in-memory database* or other data providers. Includes support for simple [database migrations](/reference-guide/database-migrations).

[**Projections**](/reference-guide/projections)\
&#x20;Support for read-model projections with various backends (e.g. *Entity Framework Core* (*PostgreSQL*, *MSSQL*, *SQLite*,...), *Entity Framework 6*, *RavenDB*...), automatic idempotency- and concurrency-handling, etc.

[**SOA, messaging and integration**](/reference-guide/integrations)\
Scale and integrate by [publishing and receiving events](/reference-guide/integrations#rabbitmq-messaging-with-easynetq), commands and queries using common messaging patterns, e.g. with *RabbitMQ* message queue (using *EasyNetQ* connector or *Rebus* service bus).

[**Sagas**](/reference-guide/sagas)\
Coordinating long-running processes or inter-aggregate cooperation with sagas that react to events (a.k.a. *process managers*).

[**Authorization**](/reference-guide/authorization)\
Basic permission/role-based ACL for commands and queries, fine-grained row filtering.

**Other minor features:**

* [**Validation**](/reference-guide/validation) for commands, queries and other structures
* [**Jobs**](/reference-guide/jobs)
* [**Multi-tenancy**](/reference-guide/multi-tenancy)
* [**Event message metadata**](/reference-guide/events#event-messages-and-metadata)
* [**Event versioning**  ](/reference-guide/events#event-versioning)
* [**Event upgrades**](/reference-guide/events#event-upgrades)
* [**Database migrations**](/reference-guide/database-migrations)
* **History and change-tracking**
* **User notifications:** event-based, with different output channels (mail, etc.), aggregation, buffering, etc.
* **.NET Core 3.0+, .NET Standard 2.0+ & .NET 4.7.2+ support (with integration for ASP.NET Core and ASP.NET)**


# Super-short example

So how does it actually look when writing an application with Revo?

These few following paragraphs show how could one design super-simple application that can save tasks using event-sourced aggregates and then query them back from a RDBMS.

{% hint style="info" %}
A little-bit more complete application based on this code, along with some walkthrough, can be found in the [Task list app example](/general/example-simple-to-dos-task-list-app).
{% endhint %}

## Event

The event that happens when changing a task's name.

```csharp
public class TodoRenamedEvent : DomainAggregateEvent
{
    public TodoRenamedEvent(string name)
    {
        Name = name;
    }

    public string Name { get; }
}
```

## Aggregate

The task aggregate root.

```csharp
public class Todo : EventSourcedAggregateRoot
{
    public Todo(Guid id, string name) : base(id)
    {
        Rename(name);
    }
    
    protectedTodo(Guid id) : base(id)
    {
    }

    public string Name { get; private set; }

    public void Rename(string name)
    {
        if (!Name != name)
        {
            Publish(new TodoRenamedEvent(name));
        }
    }
    
    private void Apply(TodoRenamedEvent ev)
    {
        Name = ev.Name;
    }
}
```

## Command and command handler

Command to save a new task.

```csharp
public class CreateTodoCommand : ICommand
{
    public CreateTodoCommand(string name)
    {
        Name = name;
    }

    [Required]
    public string Name { get; }
}
```

```csharp
public class TodoCommandHandler : ICommandHandler<CreateTodoCommand>
{
    private readonly IRepository repository;
    
    public TodoCommandHandler(IRepository repository)
    {
        this.repository = repository;
    }

    public Task HandleAsync(CreateTodoCommand command, CancellationToken cancellationToken)
    {
        var todo = new Todo(command.Id);
        todo.Rename(command.Name);
        repository.Add(todoList);
        return Task.CompletedTask;
    }   
}
```

## Read model and projection

Read model and a projection for the event-sourced aggregate.

```csharp
public class TodoReadModel : EntityReadModel
{
    public string Name { get; set; }
}
```

```csharp
public class TodoListReadModelProjector : EFCoreEntityEventToPocoProjector<Todo, TodoReadModel>
{
    public TodoListReadModelProjector(IEFCoreCrudRepository repository) : base(repository)
    {
    }

    private void Apply(IEventMessage<TodoRenamedEvent> ev)
    {
        Target.Name = ev.Event.Name;
    }
}
```

## Query and query handler

Query to read the tasks back from a RDBMS.

```csharp
public class GetTodosQuery : IQuery<IQueryable<TodoReadModel>>
{
}
```

```csharp
public class TaskQueryHandler : IQueryHandler<GetTodoQuery, IQueryable<TodoReadModel>>
{
    private readonly IReadRepository readRepository;

    public TaskListQueryHandler(IReadRepository readRepository)
    {
        this.readRepository = readRepository;
    }

    public Task<IQueryable<TodoReadModel>> HandleAsync(GetTodoListsQuery query, CancellationToken cancellationToken)
    {
        return Task.FromResult(readRepository
            .FindAll<TodoListReadModel>());
    }
}
```

## ASP.NET Core controller

Or just any arbitrary endpoint from where to send the command and queries from. :)

```csharp
[Route("todos")]
public class TodoController : CommandApiController
{
    [HttpGet("")]
    public Task<IQueryable<TodoReadModel>> Get()
    {
        return CommandBus.SendAsync(new GetTodosQuery());
    }

    [HttpPost("")]
    public Task Post([FromBody] CreateTodoDto payload)
    {
        return CommandBus.SendAsync(new CreateTodoCommand(payload.Name));
    }
    
    public class CreateTodoDto
    {
        public string Name { get; set; }
    }
}
```

## Finish!

Now you are ready save the TO-DOs to an event store and read them from regular RDBMS read models.


# Getting started

If you are new to the framework, you can

* begin with reading the quick walkthrough for the [Simple TO-DOs (task list app) example](/general/example-simple-to-dos-task-list-app)
* or try exploring the [other examples](https://github.com/revoframework/Revo/tree/develop/Examples) and [framework sources on Github](https://github.com/revoframework/Revo).

You can also start by reading the [reference guide](/reference-guide/domain-building-blocks).


# Example: Task list app

This quick guide walks you through recreating the simple TO-DOs (task list) app.

**Revo.Examples.Todos** is a simple application intended as an introduction to Revo framework. It showcases some of its most basic features including DDD-style event sourced aggregates and entities, commands and queries, projections and read models.

Using this simple application, one should be able to track his tasks to do. User can create task lists, to which tasks (to-dos) can be added (and later modified, deleted or marked as 'done').

{% hint style="success" %}
You can also instantly download the complete application by cloning the Github repository: <https://github.com/revoframework/Revo/tree/develop/Examples/Todos>
{% endhint %}

## 1. Create a new ASP.NET Core application in Visual Studio

Open Visual Studio or any other compatible IDE and create a new project targeting ASP.NET Core 3.0 or newer and add to it references to NuGet packages *Revo.Infrastructure*, *Revo.EFCore* and *Revo.AspNetCore*.

{% hint style="info" %}
We are going to write the application using **EF Core**, **ASP.NET Core** and either **PostgreSQL**, **MSSQL** or **SQLite** database (your choice), but it is also possible to easily adapt the example to other platform or database system with minor modifications.
{% endhint %}

Open the generated Startup.cs file with your ASP.NET Core's `Startup` class and modify it so that it inherits from `RevoStartup`. This adds a light-weight support for the ASP.NET Core platform and bootstraps the framework application.

```csharp
public class Startup : RevoStartup
{
    public Startup(IConfiguration configuration) : base(configuration)
    {
    }

    /*** CODE OMITTED FOR BREVITY ***/

    protected override IRevoConfiguration CreateRevoConfiguration()
    {
        return new RevoConfiguration()
            .UseAspNetCore()
            .UseEFCoreDataAccess(
                contextBuilder => contextBuilder
                    //.UseSqlite("Data Source=todos.db"), // for real applications, you'll want to switch to more featured RDBMS as shown below.
                     .UseNpgsql(connectionString) // for PostgreSQL
                    // .UseSqlServer(connectionString) // for SQL Server you will also need to comment out SnakeCaseColumnNamesConvention and LowerCaseConventionbelow
                advancedAction: config =>
                {
                    config
                        .AddConvention<BaseTypeAttributeConvention>(-200)
                        .AddConvention<IdColumnsPrefixedWithTableNameConvention>(-110)
                        .AddConvention<PrefixConvention>(-9)
                        .AddConvention<SnakeCaseTableNamesConvention>(1)
                        .AddConvention<SnakeCaseColumnNamesConvention>(1)
                        .AddConvention<LowerCaseConvention>(2);
                })
            .UseAllEFCoreInfrastructure();
    }
}
```

You also have to implement a method called `CreateRevoConfiguration()` which configures the framework. This is the place to modify many of configuration options the framework offers.

You also have to uncomment the correct line (15 - 17) depending on what database system you decided to use (PostgreSQL is recommended, but you can also start off with SQLite, for example).

## 2. Define domain model

First, we are going to define the domain model for our application. For the sake of simplicity, we are going to have only one aggregate root, which is going to be event-sourced (*Revo* also supports non-event-sourced aggregates and allows you to mix them in your domain models).

{% hint style="success" %}
If you are feeling uncertain with the terminology used in this guide, I definitely recommend reading up on topics like *domain-driven design* (DDD) or *event sourcing* elsewhere first, as explaining these concepts is greatly beyond the scope of this documentation. Great book covering many practical aspects of these topics is [*Implementing Domain-Driven Design*](https://www.amazon.com/Implementing-Domain-Driven-Design-Vaughn-Vernon/dp/0321834577) by Vaughn Vernon (2013), for example.
{% endhint %}

### 2.1. Aggregate and entities

Our only aggregate is going to be a task (to-do) list, which represents a list (e.g. a sticky note) to which individual tasks can be added. Each task list can also have its name. The task list entity (`TodoList`), which is also the aggregate root, represents an entry point to interacting with the aggregate.

```csharp
[DomainClassId("9D1C248D-A389-41CC-A93D-3419D7F1CA37")]
public class TodoList : EventSourcedAggregateRoot
{
    private Dictionary<Guid, Todo> todos = new Dictionary<Guid, Todo>();

    public TodoList(Guid id, string name) : base(id)
    {
        Rename(name);
    }

    protected TodoList(Guid id) : base(id)
    {
    }

    public string Name { get; private set; }
    public IReadOnlyCollection<Todo> Todos => todos.Values;

    public Todo AddTodo(string text)
    {
        Guid todoId = Guid.NewGuid();
        Publish(new TodoAddedEvent(todoId));

        var todo = todos[todoId];
        todo.UpdateText(text);

        return todo;
    }

    public void Rename(string name)
    {
        if (Name != name)
        {
            Publish(new TodoListRenamedEvent(name));
        }
    }

    private void Apply(TodoAddedEvent ev)
    {
        todos[ev.TodoId] = new Todo(ev.TodoId, EventRouter);
    }

    private void Apply(TodoListRenamedEvent ev)
    {
        Name = ev.Name;
    }
}
```

As you can see, we are only modifying the state of the aggregate using events, so that these modifications can later be saved in form of a sequence of events and then the state later again reloaded from these events.

The aggregate root defines one public constructor with parameters (for ensuring class invariants) and one protected constructor that takes just the aggregate ID - this one is needed for the framework to be able to load from the event store.

{% hint style="info" %}
Note that we also defined a class ID of the aggregate root using the `[DomainClassId]` attribute. This is an arbitrary GUID value (that must however be unique in your project) and is needed by Revo to identify the class when saving the aggregate.
{% endhint %}

We also need to define the entity representing a task that can be added to our list.

```csharp
[DomainClassId("D8A1F0C6-CD0A-4F66-8181-336AAFE11248")]
public class Todo : EventSourcedEntity
{
    public Todo(Guid id, IAggregateEventRouter eventRouter) : base(id, eventRouter)
    {
    }

    public bool IsComplete { get; private set; }
    public string Text { get; private set; }

    public void UpdateText(string text)
    {
        if (Text != text)
        {
            Publish(new TodoTextUpdatedEvent(Id, text));
        }
    }

    public void MarkComplete(bool isComplete)
    {
        if (IsComplete != isComplete)
        {
            Publish(new TodoIsCompleteUpdatedEvent(Id, isComplete));
        }
    }

    private void Apply(TodoTextUpdatedEvent ev)
    {
        if (ev.TodoId == Id)
        {
            Text = ev.Text;
        }
    }

    private void Apply(TodoIsCompleteUpdatedEvent ev)
    {
        if (ev.TodoId == Id)
        {
            IsComplete = ev.IsComplete;
        }
    }
}
```

### 2.2 Domain events

We wouldn't be complete without the events. Note that their state is defined as immutable (good practice).

{% tabs %}
{% tab title="TodoListRenamedEvent.cs" %}

```csharp
public class TodoListRenamedEvent : DomainAggregateEvent
{
    public TodoListRenamedEvent(string name)
    {
        Name = name;
    }

    public string Name { get; }
}
```

{% endtab %}

{% tab title="TodoAddedEvent.cs" %}

```csharp
public class TodoAddedEvent : DomainAggregateEvent
{
    public TodoAddedEvent(Guid todoId)
    {
        TodoId = todoId;
    }

    public Guid TodoId { get; }
}
```

{% endtab %}

{% tab title="TodoTextUpdatedEvent.cs" %}

```csharp
public class TodoTextUpdatedEvent : DomainAggregateEvent
{
    public TodoTextUpdatedEvent(Guid todoId, string text)
    {
        TodoId = todoId;
        Text = text;
    }

    public Guid TodoId { get; }
    public string Text { get; }
}
```

{% endtab %}

{% tab title="TodoIsCompleteUpdatedEvent.cs" %}

```csharp
public class TodoIsCompleteUpdatedEvent : DomainAggregateEvent
{
    public TodoIsCompleteUpdatedEvent(Guid todoId, bool isComplete)
    {
        TodoId = todoId;
        IsComplete = isComplete;
    }

    public Guid TodoId { get; }
    public bool IsComplete { get; }
}
```

{% endtab %}
{% endtabs %}

## 3. Writing data with commands

### 3.1. Commands

Next, we are going to implement the write-side of our application, enabling us to create and modify tasks and tasks lists. Let's start with command classes.

{% tabs %}
{% tab title="CreateTodoListCommand.cs" %}

```csharp
public class CreateTodoListCommand : ICommand
{
    public CreateTodoListCommand(Guid id, string name)
    {
        Id = id;
        Name = name;
    }

    public Guid Id { get; }

    [Required]
    public string Name { get; }
}
```

{% endtab %}

{% tab title="UpdateTodoListCommand.cs" %}

```csharp
public class UpdateTodoListCommand : ICommand
{
    public UpdateTodoListCommand(Guid id, string name)
    {
        Id = id;
        Name = name;
    }

    public Guid Id { get; }

    [Required]
    public string Name { get; }
}
```

{% endtab %}

{% tab title="AddTodoCommand.cs" %}

```csharp
public class AddTodoCommand : ICommand
{
    public AddTodoCommand(Guid todoListId, string text)
    {
        TodoListId = todoListId;
        Text = text;
    }

    public Guid TodoListId { get; }

    [Required]
    public string Text { get; }
}
```

{% endtab %}

{% tab title="UpdateTodoCommand.cs" %}

```csharp
public class UpdateTodoCommand : ICommand
{
    public UpdateTodoCommand(Guid todoListId, Guid todoId, bool isComplete,
        string text)
    {
        TodoListId = todoListId;
        TodoId = todoId;
        IsComplete = isComplete;
        Text = text;
    }

    public Guid TodoListId { get; }
    public Guid TodoId { get; }
    public bool IsComplete { get; }
    public string Text { get; }
}
```

{% endtab %}
{% endtabs %}

A command can be any POCO class that implements the `ICommand` interface. Same as with events, we make its properties immutable. A single command always represents one write operation. Its scope can vary greatly depending on the needs of your consumers (here a future REST API that we are going to write), but it is usually a good practice that one command should always *modify just one aggregate*.

In Revo, however, this is *just a recommendation,* not a requirement, and the framework doesn't limit you in what you do in your command handlers (you don't even need to work with any aggregates, for example).

{% hint style="info" %}
This concept of strictly segregating responsibilities of reading and writing (query handlers and command handlers) that Revo uses is called *CQRS* (command-query responsibility segregation). Related concept *CQS* (command-query separation) then means (simply put) that and operation always either returns data or modifies the data, not both (also *asking a question should not change the answer*).
{% endhint %}

We can also see we annotated some of command properties with the `[Required]` validation attribute, which ensures that only commands with non-empty data can get passed to the command handlers.

### 3.2. Command handler

Now we need to implement the actual code that gets executed when our commands get send to the commands bus - we do that by defining a class implementing `ICommandHandler<>` interfaces. By default, these handlers get auto-discovered and registered upon application startup, so it is enough to just define the class.

```csharp
public class TodoListCommandHandler :
    ICommandHandler<AddTodoCommand>,
    ICommandHandler<CreateTodoListCommand>,
    ICommandHandler<UpdateTodoListCommand>,
    ICommandHandler<UpdateTodoCommand>
{
    private readonly IRepository repository;

    public TodoListCommandHandler(IRepository repository)
    {
        this.repository = repository;
    }

    public async Task HandleAsync(AddTodoCommand command, CancellationToken cancellationToken)
    {
        var todoList = await repository.GetAsync<TodoList>(command.TodoListId);
        todoList.AddTodo(command.Text);
    }

    public Task HandleAsync(CreateTodoListCommand command, CancellationToken cancellationToken)
    {
        var todoList = new TodoList(command.Id, command.Name);
        repository.Add(todoList);

        return Task.CompletedTask;
    }

    public async Task HandleAsync(UpdateTodoListCommand command, CancellationToken cancellationToken)
    {
        var todoList = await repository.GetAsync<TodoList>(command.Id);
        todoList.Rename(command.Name);
    }

    public async Task HandleAsync(UpdateTodoCommand command, CancellationToken cancellationToken)
    {
        var todoList = await repository.GetAsync<TodoList>(command.TodoListId);
        var todo = todoList.Todos.First(x => x.Id == command.TodoId);
        todo.UpdateText(command.Text);
        todo.MarkComplete(command.IsComplete);
    }
}
```

The command handler's constructor gets a reference to the repository, which is used for loading and storing domain aggregates (note that you can only get an aggregate root from it, not just any entity). When a command handler executes, the command handler pipeline automatically creates and commits a new unit of work (using pipeline filters in the background). This also means that an execution of single commands defines a *strict transactional boundary*.

{% hint style="info" %}
Because the unit of work gets automatically commited at the end of a successful command execution, you don't need to explicitly call anything to save the repository.
{% endhint %}

## 4. Querying data from read model

Because we want to display the data (tasks and task lists) of our application on a simple web page, we also need a way to query the data we store in the database. Since directly querying individual events from the event store would be very cumbersome in our use case (it usually is), we are going to define a read model for our data.

### 4.1. Read model

{% tabs %}
{% tab title="TodoListReadModel.cs" %}

```csharp
[TablePrefix(NamespacePrefix = "TODOS", ColumnPrefix = "TLI")]
public class TodoListReadModel : EntityReadModel
{
    public string Name { get; set; }
    public List<TodoReadModel> Todos { get; set; }
}
```

{% endtab %}

{% tab title="TodoReadModel.cs" %}

```csharp
[TablePrefix(NamespacePrefix = "TODOS", ColumnPrefix = "TDO")]
public class TodoReadModel : EntityReadModel
{
    public Guid TodoListId { get; set; }
    public TodoListReadModel TodoList { get; set; }
    public bool IsComplete { get; set; }
    public string Text { get; set; }
}
```

{% endtab %}
{% endtabs %}

Read model can be structured pretty much in any way we or our consumers (e.g. an UI or REST API) need (even denormalized, for example). Here, for the simplicity of this example, we are going to project the events into simple POCO classes persisted by *Entity Framework Core* ORM (but you can also use other, like Entity Framework 6, RavenDB document-database or your own).

{% hint style="info" %}
`[TablePrefix]` attribute is just Revo's convenience attribute which prefixes the names of the tables and columns and you don't need to use it if you don't like it.
{% endhint %}

### 4.2. Queries

Similarly to when we defined commands to modify our data, we need to defines queries to be able to query our read model. Here, `GetTodoListsQuery` loosely corresponds to a single REST API endpoint we are going to implement.

{% tabs %}
{% tab title="GetTodoListsQuery.cs" %}

```csharp
public class GetTodoListsQuery : IQuery<IQueryable<TodoListDto>>
{
}
```

{% endtab %}

{% tab title="TodoListDto.cs" %}

```csharp
public class TodoListDto : EntityDto
{
    public string Name { get; set; }
    public List<TodoDto> Todos { get; set; }
}
```

{% endtab %}

{% tab title="TodoDto.cs" %}

```csharp
public class TodoDto : EntityDto
{
    public Guid TodoListId { get; set; }
    public bool IsComplete { get; set; }
    public string Text { get; set; }
}
```

{% endtab %}

{% tab title="DtoAutoMapperProfile.cs" %}

```csharp
public class DtoAutoMapperProfile : Profile
{
    public DtoAutoMapperProfile()
    {
        CreateMap<TodoListReadModel, TodoListDto>();
        CreateMap<TodoReadModel, TodoDto>();
    }
}
```

{% endtab %}
{% endtabs %}

Query is any class that implements the `IQuery<T>` interface, where `T` is the type of the result it returns. It can also have parameters (properties) like commands.

{% hint style="info" %}
Since we don't like directly returning the read model the way it is stored by the ORM (e.g. with recursive references), we also defines DTO (data transfer objects) mapped by [AutoMapper](https://automapper.org/), but this is purely optional and you don't need to do it in your code and your queries can directly return your read model.
{% endhint %}

### 4.3. Query handler

To define what a query returns once it is executed, we are going to implement a query handler. Query handlers get also auto-discovered and registered upon startup. Note that Revo doesn't restrict how you work with your read model in any way and you can store your data in any way you like.

```csharp
public class TaskListQueryHandler :
    IQueryHandler<GetTodoListsQuery, IQueryable<TodoListDto>>
{
    private readonly IReadRepository readRepository;

    public TaskListQueryHandler(IReadRepository readRepository)
    {
        this.readRepository = readRepository;
    }

    public Task<IQueryable<TodoListDto>> HandleAsync(GetTodoListsQuery query, CancellationToken cancellationToken)
    {
        IQueryable<TodoListDto> taskLists = readRepository
            .FindAll<TodoListReadModel>()
            .Include(x => x.Todos)
            .ProjectTo<TodoListDto>();
        return Task.FromResult(taskLists);
    }
}
```

In contrary to our command handler, our query handler works with `IReadRepository` (CRUD repository) instead of `IRepository` (domain repository).

While you should use the (and only) domain `IRepository` in command handlers to modify your aggregates, in your query handlers, you are going to need `IReadRepository` which is just a thin read-only abstraction layer over an ORM (Entity Framework Core here in our case).

{% hint style="info" %}
Compared to `IReadRepository` (which behaves just like a thin wrapper over an CRUD-like ORM), domain `IRepository` can also persist aggregates in other forms, e.g. event sourced aggregates to an event store. It also deals with other aspects of domain aggregates like publishing events to event bus.
{% endhint %}

### 4.4. Projector

Finally, we need to specify how our read model gets populated with the data from events emitted by the aggregates. To do so, we are going to implement a projector. To find out more about how projectors work, see [Projections](/reference-guide/projections) in the reference guide.

```csharp
public class TodoListReadModelProjector :
    EFCoreEntityEventToPocoProjector<TodoList, TodoListReadModel>
{
    public TodoListReadModelProjector(IEFCoreCrudRepository repository) :
        base(repository)
    {
    }

    private void Apply(IEventMessage<TodoListRenamedEvent> ev)
    {
        Target.Name = ev.Event.Name;
    }

    private void Apply(IEventMessage<TodoAddedEvent> ev)
    {
        var task = new TodoReadModel()
        {
            Id = ev.Event.TodoId,
            TodoListId = ev.Event.AggregateId
        };

        Repository.Add(task);
    }

    private async Task Apply(IEventMessage<TodoTextUpdatedEvent> ev)
    {
        var task = await Repository.FindAsync<TodoReadModel>(ev.Event.TodoId);
        task.Text = ev.Event.Text;
    }

    private async Task Apply(IEventMessage<TodoIsCompleteUpdatedEvent> ev)
    {
        var task = await Repository.FindAsync<TodoReadModel>(ev.Event.TodoId);
        task.IsComplete = ev.Event.IsComplete;
    }
}
```

## 5. ASP.NET Core controller

We have now almost all the parts for a fully functional Revo application and need just one more thing - an endpoint to send the commands and queries to our application from. We can do this by implementing an ASP.NET Core controller.

```csharp
[Route("api/todo-lists")]
public class TodoListController : CommandApiController
{
    [HttpGet("")]
    public Task<IQueryable<TodoListDto>> Get()
    {
        return CommandBus.SendAsync(new GetTodoListsQuery());
    }

    [HttpPost("")]
    public Task Post([FromBody] CreateTodoListDto payload)
    {
        return CommandBus.SendAsync(new CreateTodoListCommand(payload.Id, payload.Name));
    }

    [HttpPut("{id}")]
    public Task Put(Guid id, [FromBody] UpdateTodoListDto payload)
    {
        return CommandBus.SendAsync(new UpdateTodoListCommand(id, payload.Name));
    }

    [HttpPost("{id}")]
    public Task PostTodo(Guid id, [FromBody] AddTodoDto payload)
    {
        return CommandBus.SendAsync(new AddTodoCommand(id, payload.Text));
    }

    [HttpPut("{id}/{todoId}")]
    public Task PutTodo(Guid id, Guid todoId, [FromBody] UpdateTodoDto payload)
    {
        return CommandBus.SendAsync(new UpdateTodoCommand(id, todoId, payload.IsComplete, payload.Text));
    }

    public class CreateTodoListDto
    {
        public Guid Id { get; set; }
        public string Name { get; set; }
    }

    public class UpdateTodoListDto
    {
        public Guid Id { get; set; }
        public string Name { get; set; }
    }

    public class AddTodoDto
    {
        public string Text { get; set; }
    }

    public class UpdateTodoDto
    {
        public string Text { get; set; }
        public bool IsComplete { get; set; }
    }
}
```

We are deriving our controller from a convenience base class called `CommandApiController` which does just one thing - gets an `ICommandBus` dependency injected. A command bus can be used for sending commands and queries to an application.

## 6. Finish!

You have now implemented a complete (albeit simple) application using *Revo* framework. You can either use a REST API testing tool like Postman to manually send the requests to the API controller, or you can directly grab a simple JavaScript frontend UI that is implemented in [this example's repository](https://github.com/revoframework/Revo/tree/develop/Examples/Todos) and copy it to your project, it's your choice.

Happy testing!


# FAQ

## Who maintains this project?

This project is primarily maintained by [Olify IO s.r.o.](https://olify.io/) company and [Martin Zima](https://zimamartin.cz/). The framework is currently used in several commercial products by the company and by a few other projects. Any help or pull requests are always welcome!

## How is the framework licensed?  Can I use it my commercially?

Yes, you can. The framework is currently released under [MIT software license](https://github.com/revoframework/Revo/blob/develop/LICENSE).

##


# Configuration and boostrapping

Prior to bootstrapping a Revo application, one must first set up the framework and specify its configuration, which makes it possible to customize its behavior in a number of ways.

## Configuration

Apart from the usual possibility to specify many run-time parameters in a dynamic manner (such as loading database connection strings from configuration files), many aspects of the framework can only be altered using the programmatic configuration API. This configuration is represented by an instance of `IRevoConfiguration` , which itself is only a container for a number of `IRevoConfigurationSection` sections. When done building the configuration, the framework bootstraps the application using the parameters provided.

## Examples

Typically, the configuration object would be created at an application entry point and then configured as neccessary using fluent-style extension methods.

### ASP.NET Core

To easily bootstrap a Revo in an ASP.NET core application, simply inherit your `Startup` class from the `RevoStartup` base class and override the `CreateRevoConfiguration` method.

Example:

```csharp
public class Startup : RevoStartup
{
    public Startup(IConfiguration configuration) : base(configuration)
    {
    }

    public override void ConfigureServices(IServiceCollection services)
    {
        base.ConfigureServices(services);
        // TODO configure your services
    }

    public override void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        base.Configure(app, env, loggerFactory);
        // TODO configure your ASP.NET core app, e.g.:
        app.UseMvcWithDefaultRoute();
    }

    protected override IRevoConfiguration CreateRevoConfiguration()
    {
        string connectionString = Configuration.GetConnectionString("TodosPostgreSQL");

        return new RevoConfiguration()
            .UseAspNetCore()
            .UseEFCoreDataAccess(contextBuilder => contextBuilder.UseNpgsql(connectionString))
            .UseAllEFCoreInfrastructure();
    }
}
```

### ASP.NET

In ASP.NET applications, this would be the inside a `RevoHttpApplication`, e.g.:

```csharp
public class MvcApplication : RevoHttpApplication
{
    protected override IRevoConfiguration CreateRevoConfiguration()
    {
        return new RevoConfiguration()
            .UseAspNet()
            .UseEF6DataAccess(useAsPrimaryRepository: true, connection: new EF6ConnectionConfiguration("EntityContext"))
            .UseAllEF6Infrastructure()
            .UseHangfire();
    }
}
```


# Dependency injection

Like many other frameworks, Revo also builds on the principles inversion of control (IoC). For the heavy lifting, the framework uses the open-source Ninject dependency container and injector.

## Module auto-loading

Upon the start of an application, the framework automatically locates and loads Ninject module definitions from all referenced assemblies.

This behavior can be suppressed by decorating the module class with `[AutoLoadModule(false)]` attribute. This can be furthermore overridden (disabling implicitly enabled or re-enabling previously disabled modules) using the DI kernel [configuration API](/reference-guide/configuration), e.g.:

```csharp
new RevoConfiguration()
    ...
    .OverrideModuleLoading<XyzModule>(true);
    ;
```

In conjunction with the configuration API, this can be used, for example, for on-demand loading of module features.

## Task and request scopes

To be able to correctly resolve all dependencies in all different situations (in a command handlers, when processing a web request, when processing a message from other connected systems or when running a background job, in projections, etc.), Revo defines Ninject binding extensions for defining object life-time scope in Ninject modules.

```csharp
public static class NinjectBindingExtensions
{
    ...
    
    public static IBindingNamedWithOrOnSyntax<T> InRequestScope<T>(this IBindingInSyntax<T> syntax) { ... }
    public static IBindingNamedWithOrOnSyntax<T> InTaskScope<T>(this IBindingInSyntax<T> syntax) { ... }
    
    ...
}
```

### InTaskScope

Most of the regular services used when processing requests (command, projections...), implemented by the application end-developer, that should not be transient or global singletons, will benefit from using the `InTaskScope()` life-time scope. This scope ensures the object gets correctly created only once (singleton-like) during a task ran by the framework. A *task* could be a variety of things (processing a command with command handler, running a background job, processing an event with an async listener...). It is also the scope that most of the framework services visible to the application developer use (repositories, default command handler bindings, etc.).

Note that a single web request processing a single command mitypically consist of multiple tasks.\
If there is no current task active at time of the dependency resolution, it falls back to using the request-scope or the thread-scope (in order).

### InRequestScope

`InRequestScope` is a wrapper over what a would be a request-singleton, e.g. what official Nuget packages offer as InRequestScope for ASP.NET 4., but implemented in a more platform-independent way. In Revo, it is internally implemented by respective platform packages (e.g. *Revo.AspNetCore*). Falls-back to task-scope and thread-scope (in order) if there is no active request.

May be used for things that need to outlive the original task scopes.

## Further notes

{% hint style="info" %}
While it is possible to use the framework with other dependency container libraries, it would currently require a reimplementation of some internal dependency bindings using the specific container library, and is not very practical because of that.\
There are plans to remove this Ninject dependency and replace it with a more flexible system allowing to configure any other DI mechanisms, however.
{% endhint %}


# Domain building blocks

The domain model is one of the integral parts of applications practicing domain-driven design and also the place where most of their business logic resides. Because the implementation of the DDD is not a trivial task, the framework includes a number of basic building blocks for the model implementation.

{% hint style="info" %}
In most of the cases where working with entity identifiers, Revo framework takes an opinionated approach and chooses to use globally-unique GUIDs.
{% endhint %}

Entities

An entity can be any object that has a (be it local or global) ID and is implemented using IEntity interface. There are two predefined base classes for entities – `BasicEntity` and `EventSourcedEntity` (see below for more information). Entities are always a member of an aggregate.

Aggregates

Aggregates are one of the most important concepts in DDD defining the consistency and transaction boundaries. They are implemented by aggregate roots as an `IAggregateRoot` (which itself is also an entity) that provide a public interface for working with the aggregate.

### Basic aggregates and entities&#xD;

`BasicAggregateRoot` and `BasicEntity` define base classes for aggregate roots and entities which will be persisted using their visible state (typically perstisting their public properties) to an RDBMS using an ORM or to a document-oriented database. Alone deriving from these base classes will be enough to be picked-up be Revo's selected persistence implentation (e.g. EF Core).

{% hint style="info" %}
Any class annotated with`DatabaseEntityAttribute` (just like these basic aggregate base classes) will be automatically be mapped to database using their public state (e.g. using EF Core if you are using Revo.EFCore as your primary data repository). For more see [Data persistence](/reference-guide/data-persistence).
{% endhint %}

These base classes also implement `IQueryableEntity` which means it will be possible to query them as `IQueryable` with repositories. By default, they will be automatically row-versioned to implement optimistic concurrency when saving them to a database (increasing their version number with each save).

For compatibility with ORMs like EF Core, these basic entities will usually need to define a parameterless constructor (which may be `protected` ; this means it should not limit your from exposing another proper public constructor taking parameters and ensuring entity invariants).

### Event sourced aggregates&#xD;

Event sourced aggregates implemented using `EventSourcedAggregateRoot` and `EventSourcedEntity` will use events to progress their state. Unlike the basic entities, they should only modify their state upon emitting a new event. Aggregates can internally publish new events using the `Publish<TEvent>` method. This pushes the event to the internal queue of uncommitted events that will get persisted once the repository is saved and invokes an event handler for the specific event type that actually produces the effect of modifying the internal state of the aggregate (e.g. changes the values of its fields). The same event handlers get also invoked when the aggregate gets loaded from a repository.

{% hint style="info" %}
When loading an event-sourced aggregate, the repository first creates a blank instance of the aggregate and then replays all the events that the aggregate published previously – effectively reconstructing its complete state. It is obvious that it is vital for event-sourced aggregates to only use event for progressing their state as change made in any other way will get lost upon the next loading.
{% endhint %}

{% hint style="warning" %}
For the repository to be able to create new instances of event sourced aggregate roots (e.g. when loading them from the event store), the aggregate roots always need to define a constructor accepting a single `Guid id` parameter. However, similarly to (non-event-sourced) *basic aggregates*, this constructor can be kept protected or private (being used only for the needs of deserialization) and the aggregate can define other public constructor(s) that will normally enforce its invariants by requiring more parameters. See also the example below.
{% endhint %}

`EventSourcedAggregateRoot` and `EventSourcedEntity` use a convention-based event handling by default and will invoke any methods with the following signature:

```csharp
void Apply(TEvent);
```

(considering `TEvent` is the type of the event handled).

These methods need to be either private, protected or internal (non-public in general). Furthermore, all events published by an aggregate need to derive from `DomainAggregateEvent`. This domain type includes the aggregate ID which gets automatically injected when publishing the event within an aggregate.

### Example

Here is a contrived example of a simple event sourced aggregate publishing and handling events:

{% tabs %}
{% tab title="Ticket.cs" %}

```csharp
[DomainClassId("061ABAC8-7BE0-46D6-A6DB-BA8593027EC9")]
public class Ticket : EventSourcedAggregateRoot
{
    public Ticket(Guid id, string subject)
        : base(id)
    {
        Publish(new TicketStateChangedEvent(TicketState.Open));
        Rename(subject);
    }

    protected Ticket(Guid id) : base(id)
    {
    }

    public string Subject { get; private set; }
    public TicketState State { get; private set; }

    public void Rename(string subject)
    {
       if (Subject != subject)
       {
           Publish(new TicketRenamedEvent(subject));
       }
    }

    public void Resolve()
    {
        if (State == TicketState.Resolved)
        {
            throw new InvalidOperationException(
                $"{this} has already been resolved");
        }

        Publish(new TicketStateChangedEvent(TicketState.Resolved));
    }

    private void Apply(TicketRenamedEvent ev)
    {
        Subject = ev.Subject;
    }
    
    private void Apply(TicketStateChangedEvent ev)
    {
        State = ev.State;
    }
}
```

{% endtab %}

{% tab title="TicketState.cs" %}

```csharp
public enum TicketState
{
    Open, Resolved
}
```

{% endtab %}

{% tab title="TicketStateChangedEvent.cs" %}

```csharp
public class TicketStateChangedEvent : DomainAggregateEvent
{
	public TicketStateChangedEvent(TicketState state)
	{
		State = state;
	}

	public TicketState State { get; }
}
```

{% endtab %}

{% tab title="TicketRenamedEvent.cs" %}

```csharp
public class TicketRenamedEvent : DomainAggregateEvent
{
	public TicketRenamedEvent(string subject)
	{
		Subject = subject;
	}
	
	public string Subject { get; }
}
```

{% endtab %}
{% endtabs %}

### Event routing inside an aggregate

Entities that are part of an event-sourced aggregate can also participate in the even-driven architecture. Any event-sourced entity can react to the publishing of an event inside an aggregate (i.e. not just event published by itself, but also events published by other entities or the aggregate root itself). For that, it is enough to simply derived from `EventSourcedEntity` or directly `EventSourcedComponent`, passing in the event router from the aggregate root (its `EventRouter`). The event router takes care of routing the events inside the aggregate, delivering them to all registered components. With that, the event sourced entities and components can use the same `Apply` method convention for handling events as with aggregate root and use the event router for publishing new events.&#x20;

As already mentioned, it is also possible to compose the aggregate roots and entities of several smaller components that are however not entities of their own (i.e. they have no distinct identity). To do that, all that is needed is to derive from `EventSourcedComponent` instead of `EventSourcedEntity` instead.

## Domain events

A basic insight on how to implement domain events in aggregates was provided in previous parts named [Event sourced aggregates](/reference-guide/domain-building-blocks#event-sourced-aggregates) and [Event routing inside an aggregate](/reference-guide/domain-building-blocks#event-routing-inside-an-aggregate).

Although events are mostly discussed in connection to event-sourced aggregates, the framework has a notable feature which allows you to publish even in [basic aggregates](/reference-guide/domain-building-blocks#basic-aggregates-and-entities) while still providing the same transactional delivery guarantees (when saving a basic aggregate to an RDBMS, both the aggregate and the events published by it get saved inside one transaction and the events get processed only after successfully persisting them).

{% hint style="success" %}
For more info on events and their processing, see chapter [Events](/reference-guide/events).
{% endhint %}

This means you can use events as a powerful means of inter-aggregate communication (or even cross-system communication) or to simply implement an event-driven driven architecture (e.g. you can asynchronously trigger actions using an event listener anytime a modified aggregate publishes an event).

You can publish events from inside an aggregate using its protected `Publish` method:

```csharp
protected virtual void Publish(T evt) where T : DomainAggregateEvent
```

## Value objects

Value objects represent another option how to implements objects in an aggregate. In domain-driven design, value objects have no identity and should usually be immutable (this is different from entities which have an identity and a mutable state, which also implies having a clearly defined life time and scope, contrary to value objects). As such, an instance of a value object would usually be treated as a single value that is fully defined by the set of the properties it encapsulates.

The framework provides a basic support for easier implementation of these objects. This is primarily achieved with the `ValueObject<T>` abstract base class that implements basic value-like semantics. An example follows.

```csharp
public class Reward : ValueObject<Reward>
{
    public Reward(string awardedTitle, ImmutableDictionary<string, decimal> tokens)
    {
        AwardedTitle = awardedTitle;
        Tokens = tokens;
    }

    public string AwardedTitle { get; }
    public ImmutableDictionary<string, decimal> Tokens { get; }

    protected override IEnumerable<(string Name, object Value)> GetValueComponents()
    {
        yield return (nameof(AwardedTitle), AwardedTitle);
        yield return (nameof(Tokens), Tokens.AsValueObject());
    }
}
```

Out-of-the box, `ValueObject<T>` (with `T` being a self-reference to the value object type implemented) overrides `object.Equals`, `IEquatable<T>.Equals`, `GetHashCode` and `ToString` methods making it possible to treat the instances of the object as a single value - e.g. they can be correctly used in HashSets, as Dictionary keys, compared between each other, etc. (with objects having the same values considered to be equal, very much unlike with the default behavior of C# classes which considered references only), e.g.:

```csharp
Reward first = new Reward("Hero", new Dictionary<string, decimal>() { { "TKN", 1000 } });
Reward second = new Reward("Hero", new Dictionary<string, decimal>() { { "TKN", 1000 } });
Assert.Equals(first, second); // passes
```

To be able to do so, it only needs to know what the components making up the object value are. These are defined by overriding `GetValueComponents` method as shown previously.

{% hint style="info" %}
Please be aware that because the hash codes should usually be constant for an object instance, the GetValueComponents method should not return values of any mutable fields. As previously stated, it is also generally a good idea to keep value objects fully immutable.
{% endhint %}

### Collection value helpers

Note that the GetValueComponents method is expected to return objects which correctly implement their Equals/GetHashCode/ToString methods. While this will be true by default for most of the C# language primitives (e.g. number types, strings, etc.), it does not hold up for the collections types (e.g. lists, dictionaries or sets) which use the default class by-reference comparisons. To be able to correctly use them in value objects, the framework defines a number of helpers which wrap them as a value. `CollectionAsValueExtensions` implements the following extension methods (abridged code snippet):

```csharp
public static class CollectionAsValueExtensions
{
	public static IEnumerable<T> AsValueObject<T>(this IImmutableList<T> list);
	public static IEnumerable<T> AsValueObject<T>(this ImmutableArray<T> array);
	public static IEnumerable<T> AsValueObject<T>(this IImmutableSet<T> set);
	public static IReadOnlyDictionary<TKey, TValue> AsValueObject<TKey, TValue>(this IImmutableDictionary<TKey, TValue> dictionary);
}
```

As shown in the previous value objects example, these methods can be used in the `GetValueComponents` method to wrap lists, arrays, sets and dictionaries with correct value-object-like semantics.

## Sagas

The framework implements a comprehensive support for long-running process coordination using sagas. Thanks to this support, sagas can be considered first-class citizens of the domain model. Because of complexity of this topic, there is a [separate chapter](/reference-guide/sagas) dedicated to them.


# Commands and queries

The framework implements a number of facilities for working with commands, queries and for implementing CQRS.

## Commands, queries

Commands and queries can be defined as regular POCO classes implementing `ICommand` or `IQuery<T>` (with `T` defining the query return type) interfaces. These interfaces are empty on their own and only define the contract of being processable by a command bus.

{% hint style="info" %}
Because both `IQuery` and `ICommand` derive from a common `ICommandBase` ancestor, the framework considers queries to be simply a specific subtype of commands that happen to also return a value.
{% endhint %}

&#x20;Example command:

```csharp
public class CreateUserCommand : ICommand
{
    public CreateUserCommand(string firstName, string lastName,
      string emailAddress, string password)
    {
        FirstName = firstName;
        LastName = lastName;
        EmailAddress = emailAddress;
        Password = password;
    }

    public string FirstName { get; }
    public string LastName { get; }
    public string EmailAddress { get; }
    public string Password { get; }
}
```

&#x20;Example query:

```csharp
public class GetAllUsersQuery : IQuery<List<UserDto>>
{
    public GetAllUsersQuery(string filterFirstName, string filterLastName)
    {
        FilterFirstName = filterFirstName;
        FilterLastName = filterLastName;
    }

    public string FilterFirstName { get; }
    public string FilterLastName { get; }
}
```

{% hint style="success" %}
It is advisable to make the command/query classes immutable (as can be seen in the example) to prevent undesirable modifications as the object gets passed throughout the system.
{% endhint %}

## Command/query handlers

Commands and queries can be handled by implementing `ICommandHandler<TCommand>` or `IQueryHandler<TQuery, TResult>` respectively. For every command or query type, there should be exactly one handler type registered in the dependency container, otherwise an exception will be thrown when trying to handle it.

```csharp
public interface ICommandHandler<in TCommand>
	 where TCommand : ICommand
{
	Task HandleAsync(T command, CancellationToken cancellationToken);
}

public interface ICommandHandler<in TCommand, TResult>
	where TCommand: ICommand<TResult>
{
	Task<TResult> HandleAsync(TCommand query, CancellationToken cancellationToken);
}

public interface IQueryHandler<TQuery, TResult>
    : ICommandHandler<TQuery, TResult>
	where TQuery : IQuery<TResult>
{
}
```

{% hint style="info" %}
By default, all command and query handlers get auto-discovered in all referenced assemblies and registered in [task scope](/reference-guide/dependency-injection#intaskscope).
{% endhint %}

Command bus

To send a command or query to the system, one can use an `ICommandBus` which encapsulates most of the command processing details.

```csharp
public interface ICommandBus
{
	Task<TResult> SendAsync<TResult>(ICommand<TResult> command,
		CancellationToken cancellationToken = default(CancellationToken));
	Task SendAsync(ICommandBase command,
        CancellationToken cancellationToken = default(CancellationToken));
}
```

The command bus is designed to accept any command or query type an resolves the corresponding handlers during runtime. By default, the command handling also starts a new unit of work that is automatically committed at the end of the handling pipeline – to find more about this, see chapter describing the [request life-cycle](/reference-guide/request-life-cycle).

### Command filters

Command filters provide a way for dealing with cross-cutting concerns when handling their execution. It is possible to define action that will get executed before invoking a command handler, after invoking it and after invoking it in case it results in an error exception.

```csharp
public interface IPreCommandFilter<in T>
	where T : ICommandBase
{
	Task PreFilterAsync(T command);
}

public interface IPostCommandFilter<in T>
    where T : ICommandBase
{
	Task PostFilterAsync(T command, object result);
}

public interface IExceptionCommandFilter<in T>
    where T : ICommandBase
{
	Task FilterExceptionAsync(T command, Exception e);
}
```

These filters get automatically invoked when registered in the dependency container for a specific command (base) type. The framework uses them to deal with concerns like authorization or automatic unit-of-work management, but it is also possible to define custom application’s own filters.


# Events

Events are one of the most powerful ways of communication used in Revo. The framework offers a few different ways for implementing an event-driven architecture.

## Quick start

There is a number of reasons you'd want to publish events, e.g.:

* progress the state of an [event sourced aggregate](/reference-guide/domain-building-blocks#event-sourced-aggregates),
* [project read model](/reference-guide/projections#entity-event-projections) from these events for such aggregates,
* use it as a mean for inter-aggregate communication (event-driven architecture in DDD),
* communicate across system boundaries ([integrations](/reference-guide/integrations#rabbitmq-messaging-with-easynetq)).

This part shows how to define an event, implement an event listener, register it and publish an event in the simplest manner. Further elaboration on how the system works is provided in later chapters.

{% hint style="info" %}
Please note that this is primarily intended for more advanced usage scenarios or learning the framework architecture. You generally don't need to write your own listeners when you just want to use projections.
{% endhint %}

### Define an event

```csharp
public class ShoppingCartItemAddedEvent : DomainAggregateEvent
{
	public ShoppingCartItemAddedEvent(Guid customerId, Guid itemId, int amount)
	{
	  CustomerId = customerId;
		ItemId = itemId;
		Amount = amount;
	}
	
	public Guid CustomerId { get; }
	public Guid ItemId { get; }
	public int Amount { get; }
}
```

### Implement an event listener

* **I need at-least-once delivery and event processing order guarantees.**\
  → Implement an async event listener along with an event sequencer:

```csharp
public class ShoppingCartEventListener :
    IAsyncEventListener<ShoppingCartItemAddedEvent>
{
    private readonly IMarketingServiceApi marketingServiceApi;

    public SubmissionProcessingEventListener(SubmissionProcessingEventSequencer eventSequencer,
        IMarketingServiceApi marketingServiceApi)
    {
        EventSequencer = eventSequencer;
        this.marketingServiceApi = marketingServiceApi;
    }

    public async Task HandleAsync(IEventMessage<ShoppingCartItemAddedEvent> message, string sequenceName)
    {
        await marketingServiceApi.NotifyCustomerIsInterestedAsync(
            message.Event.CustomerId,
            message.Event.ItemId);
    }

    public Task OnFinishedEventQueueAsync(string sequenceName)
    {
        return Task.CompletedTask;
    }

    public IAsyncEventSequencer EventSequencer { get; }

    public class SubmissionProcessingEventSequencer : AsyncEventSequencer<ShoppingCartItemAddedEvent>
    {
        public readonly string QueueNamePrefix = "ShoppingCartEventListener:";

        protected override IEnumerable<EventSequencing> GetEventSequencing(IEventMessage<ShoppingCartItemAddedEvent> message)
        {
            yield return new EventSequencing()
            {
                SequenceName = QueueNamePrefix + message.Event.AggregateId.ToString(),
                EventSequenceNumber = message.Metadata.GetStreamSequenceNumber()
            };
        }

        protected override bool ShouldAttemptSynchronousDispatch(IEventMessage<ShoppingCartItemAddedEvent> message)
        {
            return false;
        }
    }
}
```

* **I don't care about delivery guarantees or don't want the overhead of async events**\
  (typically only a few usage scenarios, see following chapters for details).\
  → Implement a regular event listener:

```csharp
public class ShoppingCartEventHandler
   : IEventHandler<ShoppingCartItemAddedEvent>
{
	public ShoppingCartEventHandler()
	{
	}
	
	public Task HandleAsync(IEventMessage<ShoppingCartItemAddedEvent> message, CancellationToken cancellationToken)
	{
		Console.WriteLine($"Hey, a customer is interested in a product: {message.Event.ItemId}!");
	}
}
```

### Register the event listener

```csharp
public class MyModule : NinjectModule
{
    public override void Load()
    {
        // when using async listener
        Bind<IAsyncEventSequencer<ShoppingCartItemAddedEvent>, ShoppingCartEventHandler.SubmissionProcessingEventSequencer>()
            .To<ShoppingCartEventHandler.SubmissionProcessingEventSequencer>()
            .InTaskScope();

            Bind<IAsyncEventListener<ShoppingCartItemAddedEvent>>()
            .To<ShoppingCartEventHandler>()
            .InTaskScope();
        
        // when using regular listener
        Bind<IEventListener<ShoppingCartItemAddedEvent>>()
            .To<ShoppingCartEventHandler>()
            .InTaskScope();
    }
}
```

### Publish the event

Either,

* **Publish an event from an aggregate, in a transactional manner (alongside saving the aggregate changes to database):**

```csharp
[DomainClassId("F23D8F21-D2A4-4B47-BC64-8D01795A3471")]
public class ShoppingCart : EventSourcedAggregateRoot
{
    /** CODE OMITTED FOR BREVITY **/

    public void AddItem(ShopItem item, int amount)
    {
        /** omitted some business logic here... **/
        
        Publish(new ShoppingCartItemAddedEvent(item.Id,
          this.CustomerId, amount));
    }

    /** ... **/
}
```

* **Publish an event from anywhere else, e.g. straight from a command handler or from an external source:**

```csharp
IEventBus eventBus = ...;

// ... somewhere later in code ...

await eventBus.PublishAsync(
    EventMessage.FromEvent(
        new ShoppingCartItemAddedEvent(
            Guid.Parse("1DCF3A44-6343-48C9-8E34-A8C8C8F0D26F"),
            Guid.Parse("2AEEB591-53BF-4DE8-90FD-DBBDF3C7FFE1"),
            1),
        new Dictionary<string, string>()
        {
            { BasicEventMetadataNames.EventSourceName, "SupplierApi@1.2.3.4" }
        }));
```

## General overview

### Events and listeners

Framework defines a generic event listener `IEventListener<TEvent>` interface. Event can be any plain object that implements the IEvent interface (which itself is empty in its definition).&#x20;

```csharp
public interface IEvent
{
}
```

```csharp
public interface IEventListener<in T>
	where T : IEvent
{
   Task HandleAsync(IEventMessage<T> message,
      CancellationToken cancellationToken);
}
```

Because the generic event parameter in the event listener interface is defined as contravariant and so is the actual listener resolving mechanism under the hood of default event bus implementation, it is also possible to listen for more general base types of events (e.g. `DomainEvent` listener will also receive events of type `DomainAggregateEvent` and all types derived from it). Single event type can be handled by any amount of event handlers, which are registered using the dependency container (their order of invocation is not guaranteed in any way).

An example of an event with a corresponding event handler can be found below.

```csharp
public class ShoppingCartItemAddedEvent : IEvent
{
	public ShoppingCartItemAddedEvent(Guid customerId, Guid itemId, int amount)
	{
		CustomerId = customerId;
		ItemId = itemId;
		Amount = amount;
	}
	
	public Guid CustomerId { get; }
	public Guid ItemId { get; }
	public int Amount { get; }
}
```

As you can see in the previous code listing, it is considered a good practice to make the event classes immutable in order to ensure their data never changes once they are created.

### Event messages and metadata&#xD;

The HandleAsync does not take the event itself as an argument, but rather an event message (`IEventMessage<T>`). Event message is an envelope wrapping the event with additional metadata that may not be primarily important for the domain (i.e. they are not a part of the event’s definition on its own), but still might be needed elsewhere (especially when consuming the events outside of the domain model core). This allows to keep the event type definitions simple and clean of things unrelated to their purpose from the domain perspective.

```csharp
public interface IEventMessage
{
	IEvent Event { get; }
	IReadOnlyDictionary<string, string> Metadata { get; }
}

public interface IEventMessage<out TEvent> : IEventMessage
	where TEvent : IEvent
{
	new TEvent Event { get; }
}
```

These additional metadata are represented in form of a string key-value dictionary. Notable examples of such metadata include timestamp or event stream sequence number but might also optionally include other data used solely for other purposes like debugging, for example the name of the machine, that first created the event, or the command and URI of the sever request that triggered the creation of the event. The names for the predefined event metadata keys are defined in class `BasicEventMetadataNames`.

Additional metadata can be appended to event messages by registering new implementations of `IEventMetadataProvider` in the DI container. These providers are invoked by the `EventMessageFactory` when the event messages get constructed (i.e. typically before saving to event store or sending to other connected systems).

### Event bus&#xD;

The entry point for system-wide distribution of events is the event bus. Primarily, it handles the routing of events to listeners that are registered for the specified type(s) of events (basically, it implements a simple messaging bus functionality – see chapter 6.4 for more details about this pattern). When publishing an event, the event bus then iterates through all listeners registered for the type of the specified event (or for a base type of it) and invokes them.&#x20;

```csharp
public interface IEventBus
{
	Task PublishAsync(IEventMessage message,
        CancellationToken cancellationToken = default(CancellationToken));
}
```

### Event versioning&#xD;

The framework implements a versioning system for events. There are situations when a need for changing the definition of an event arises - business domain requirements change over time, bugs get fixed and you may sometimes end up needing to change the definition of your domain classes and their events. Because the events in the event store in general cannot be modified once saved, it is possible to define multiple versions of the same event class. The type information when saving an event into an event store consists of event type name + event type version, so the system is able to correctly lookup the corresponding CLR type.

By default, any event class will be considered to be of version 1. When introducing a new version of the event, you can simply create a copy of the old event class and suffix its name with “V” + the number of its version. After that, the original event class updated with the new event definition is to be annotated with an `EventVersionAttribute` specifying its new version (which makes it possible to preserve its original name). An example:

```csharp
// Your new event class
[EventVersion(2)]
public class PageBookmarkedEvent : IEvent
{
	public PageBookmarkedEvent(string pageUrl, string folderName)
	{
	    PageUrl = pageUrl;
	    FolderName = folderName;
	}
	
	public string PageUrl { get; }
	public string FolderName { get; } // added new attribute in V2
}
```

```csharp
// Your original event class
public class PageBookmarkedEventV1 : IEvent
{
	public PageBookmarkedEvent(string pageUrl)
	{
	    PageUrl = pageUrl;
	}
	
	public string PageUrl { get; }
}
```

Note that this does not replace the old instances of the event (like automatically upgrading them to the newer version), so you either need to keep the event handlers for both of the versions of the event (less practical approach) or implement appropriate [event upgrades](/reference-guide/events#event-upgrades).

### Event upgrades

Once your application matures and you define more [historical versions](/reference-guide/events#event-versioning) of your events, it would become cumbersome to maintain handlers (ApplyEvent methods in event-sourced aggregates...) for all the previous and current versions at once. To mitigate this, framework offers automatic event upgrades based on the event transformations you define.

Event upgrades are applied any time an event-sourced aggregate is loaded from an event store and the aggregate is then loaded with the new, upgraded events. All you have to do to implement an event upgrade is to define a class deriving from `IEventUpgrade` (Revo auto-discovers these upon startup).

{% hint style="info" %}
For most cases, it is recommended to use the generic `EventUpgrade<TAggregate>` class as a base class for your upgrades, which also check the aggregate class before trying to apply any upgrades (which is more efficient if the event is used by only one aggregate class).
{% endhint %}

```csharp
public class BookmarkCollectionEventUpgrade : EventUpgrade<BookmarkCollection>
{
    protected override IEnumerable<IEventMessage<DomainAggregateEvent>> DoUpgradeStream(IEnumerable<IEventMessage<DomainAggregateEvent>> events)
    {
        foreach (var message in events)
        {
            if (message.Event is PageBookmarkedEventV1 pageBookmarkedEventV1)
            {
                yield return message.Upgrade(new PageBookmarkedEvent(message.Event.PageUrl, "Root"));
            }
            else
            {
                yield return message;
            }
        }
    }
}
```

An event upgrade takes a stream (`IEnumerable`) of all original aggregate's event messages and then returns an upgraded stream of event messages. You can easily implement this transformation using C# `yield return` operator.

{% hint style="success" %}
As you can see in the previous code The framework implements a helper function `EventMessageUpgradeExtensions.Upgrade<TSource>` for upgrading the event message, which returns a new event message with the domain event replaced while keeping all original message metadata.
{% endhint %}

For code brevity, there are also a few helper methods in `EventMessageUpgradeExtensions` class making the transformation even easier, e.g.:

```csharp
return events
    .Replace<PageBookmarkedEventV1>(message => new DomainAggregateEvent[]
    {
        new PageBookmarkedEvent(message.Event.PageUrl, "Root")
    })
    .Remove<SomeOldCompletelyRedundantEvent>();
```

{% hint style="warning" %}
&#x20;At this moment, event upgrades do not work for your arbitrary event listeners that you have defined and are used **only for event-sourced aggregate loading**. This means that if you get an event from an external out-dated system or you have any unprocessed queued events of an outdated version, these events won't be automatically upgraded and you have to implement their support manually.
{% endhint %}

Synchronous event processing

The flow of events from publisher to regular listeners (`IEventListener<TEvent>`) via the event bus is the basic way of processing events that is implemented by the framework. As such, it is completely synchronous – meaning that all the listeners are invoked sequentially, one-by-one and without guaranteed order, in a synchronous manner. Because of their nature, synchronous event listeners posess *no delivery guarantees* and should *rarely be used* in actual application code (possible valid use cases include notifications that only have transient effects).

{% hint style="info" %}
No synchronous listener is invoked before all preceding listeners have finished processing of the event. Furthermore, if any of the listeners fails, following listeners will not get invoked. This also impedes system performance in situations where multiple listeners could have been ran in parallel and also means that the entire processing stalls any further processing of the (HTTP) request whose handling originally caused publishing of the event.
{% endhint %}

{% hint style="success" %}
The distinction between synchronous and asynchronous event processing made here *does not refer* to the`async/await`features of C# (the Task Asynchronous Pattern ak TAP; in fact, most of the framework codebase is already *async all the way*), but rather to the a/synchronicity of the event delivery and processing itself in regard to the event publishing and to other listeners.
{% endhint %}

Asynchronous event processing

This framework introduces the concept of asynchronous listeners as a more practical approach to event processing, effectively dealing with the issues that synchronous listeners have. Akin to their synchronous counterparts, asynchronous (or just async for short) listeners are defined by implementing `IAsyncListener<TEvent>` for the specific event (base) type and registered using the dependency container. Events asynchronously delivered via this interface are a bit different in their nature when compared to the events delivered using the regular (synchronous) event pipeline.

Firstly, asynchronous events have guaranteed delivery. This means that once an event gets accepted for the asynchronous processing, it will be delivered at least once (a.k.a. *at-least-once delivery*). For practical reasons, the system does not guarantee if the event gets delivered once or more than once and naturally it cannot guarantee when will the actual delivery happen. This is achieved using an intermediate persistent buffer to store the events that have not been fully processed (with all registered asynchronous listeners) yet. If an event listener was to fail, the asynchronous event processor can always retry later using this saved data.

Another important aspect previously discussed in regard to the asynchronous nature of event processing was ordering of the events delivered. In order to be able to guarantee that the listeners will always receive events in order (if they signal they need to, as this may not be a requirement for all asynchronous listeners), the system works with asynchronous event queues. With those, every async event listener is able to define its event sequencing requirements for every particular event. To do so, every async listener also needs to register its own event sequencer (`IEventSequencer<TEvent>`). When the async processing of an event begins, the event dispatcher calls all of these registered sequencers. An event sequencer primarily defines two properties – which event sequence(s) it wants to use for the event (which in turn implies the event queue it will be pushed to) and what sequence number(s) will it assign to that event. Based on that information, the event dispatcher subsequently creates corresponding event queues (if it does not exist already) and pushes the event to them. Later when an event backlog worker gets to process any of the queues, it iterates through all the events queued in it, ordered by their sequence number, and passes them to corresponding async event listener(s). When the backlog worker is done, it removes the events that were successfully processed from that queue. If processing of any of the events fails, it stays in the queue until the problem gets resolved and event successfully processed.

There is an important property of all event queues, which is that they always remember the sequence number of last successfully processed event (which gets updated in a transactional manner when events get dequeued from it). As long as there are gaps in the event sequence (at the beginning or possibly in the middle), the worker will block their processing until the sequence is fixed. Similarly, if the worker encounters events with sequence number lower than the number of last event processed in the queue, it skips them to avoid duplication of work (thus providing certain degree of idempotency). Once the sequence becomes fixed again and a worker starts processing the queue again, it dispatches both older events that were backlogged in the queue and the latest events that just got pushed to the queue in a single batch. This has several repercussions to the application design, but also automatically provides strong guarantees for the listeners that need it.

Because not all listeners require these strict ordering rules, any event sequencer can also declare an event to have no sequence number. These events will then be processed separately from sequenced events. This has the upside that these events will not be blocked by other possibly missing events in a sequence, meaning they can always be processed immediately. It is obvious, however, that the use of non-sequenced events will be appropriate under slightly different circumstances.

Depending on the current configuration of the system (i.e. maximum number of Hangfire thread that are used for background job execution), the framework will also allow concurrent processing of multiple event queues in parallel.

Eventual synchronization of event sources

This mechanism described so far still does not solve the error-case scenario when the system fails to dispatch and save the events into queues. Without the events dispatched to corresponding queues, event queues will likely contain gaps in their sequences as soon as any later events arrive in it, blocking any further processing of sequenced events in them. The framework works around this issue using event catch-ups. The event catch-up process consists of three steps:

&#x9;1\.	Pulling non-dispatched events from all event stores. Different kinds of event stores can\
&#x9;	implement this by implementing their own version of `IEventSourceCatchUp` interface.

&#x9;2\.	Dispatching these events into corresponding async event queues.

&#x9;3\.	Running async event queue workers for queues that are lagging behind with any unprocessed\
&#x9;	(backlogged) events.

These catch-ups are ran regularly:

* &#x9;During the application start-up, before processing of any new requests starts.
* &#x9;Periodically in pre-defined (configured) time intervals.&#x20;

This ensures that all event sources get eventually back into a synchronized state. As noted before, while the regular event-processing path in the success-case scenarios works completely as a *push-based* mechanism (i.e. the events get propagated throughout the pipeline actively by their initiator at the time they are created), which usually should have better efficiency in the use-case mentioned, the catch-ups resort to employing different *pull-based approach* when loading events from the event store.

{% hint style="info" %}
Despite the fact that catch-ups could also deliver events to synchronous event listeners, it was decided they would rather not. This design decision stems from the fact that synchronous dispatchers cannot safely guarantee some other delivery properties (like ordering) and thus they should be kept completely that way with no delivery guarantees altogether to make a clear distinction from asynchronous events. Therefore, they should only be used for actions that have transient effects.
{% endhint %}

Pseudo-synchronous event dispatch

Even though the asynchronous event processing offers many advantages over the synchronous processing (i.e. scalability, reliability…), dealing with the consequences of its eventual consistency in relation to the originating event publishing can sometimes be difficult. For example, system might occasionally want to guarantee that when a processing of a request finishes, all its effects on the read model have already been applied as well, which would normally be complicated. To remedy this, the framework offers the possibility of attempted synchronous event dispatch even for asynchronous event handlers.

When any `IAsyncEventSequencer` signals that it wants to attempt synchronous dispatch by implementing`ShouldAttemptSynchronousDispatch`, the events added to its queue that would normally get scheduled for later processing in the background get directly passed to the event processor instead - that is, in a blocking (synchronous) manner, possibly on the same thread. If any of the async event listeners fail, they still retain the same properties of other asynchronous events – i.e. their processing gets retried later either upon the restart of the system or at the next processing of the same queue.

Processing idempotency

As the chapter discussing asynchronous event processing already mentioned, the event pipeline can only guarantee *at-least-once delivery* of events. This also means that some events may occasionally get delivered more than just once. This is important for the design of actual async event listener implementations, because they need to account for these scenarios. It is necessary that repeated submission of a single event will not change the final result. In mathematics and informatics, this is property also called *operation idempotency*.

Some listeners built-in to the framework already minimize or completely remove the need to do so (it is however still required to handle this manually ad-hoc in other cases). One of the automatically handled use cases are read model projections when implemented using `EntityEventToPocoProjectors<,>` along with projection row versioning (see later chapter on [read models and projections](/reference-guide/projections)).&#x20;


# Data persistence

## Repositories

Revo framework offers a number of facilities for working with entities and their persistence. Repositories are one of the core concepts in framework’s data persistence. There are two distinct types of repositories that a developer can use. Both of them come with a certain level of implementation abstraction.

### Aggregate repository

In terms of domain-driven design, `IRepository` (defined in Revo.Infrastructure module) is the high-level repository that would be used in the command handlers for the write side of the application working with the domain model.

{% hint style="info" %}
The implementation of `IRepository` interface is not bound to any specific database system backend (or an ORM library) and instead delegates most of the actual data-persistence related responsibilities to different *aggregate stores -* i.e. **event sourced aggregate store** or **CRUD aggregate store**. The repository itself is then just a thin wrapper over those aggregate stores, making it easier to work with aggregate stored in different persistence backends by providing a single unified API for them while also handing some of the concepts related to domain repositories – like the unit-of-work pattern and event publishing.
{% endhint %}

The repository declares all methods as generic, simplifying all repository interactions to just one universal interface. When querying for an entity, the repository itself then tries to deduce the aggregate store it belongs. When the correct aggregate store is found, the repository delegates the actual persistence work (loading, saving, querying…) to it.

To enforce aggregate consistency boundaries on compliance with DDD rules, repositories only allow working with aggregate roots, which is enforced by generic type constraints for all its generic methods (requiring any `IAggregateRoot` descendant). This prevents breaking the encapsulation of aggregates by querying and manually modifying single aggregate entities separately.

Following  abridged code snippet of `IRepository` interface definition shows some of the basic functionality it offers for working with aggregates.

```csharp
public interface IRepository : IUnitOfWorkProvider, IDisposable
{
	void Add<T>(T aggregate) where T : class, IAggregateRoot;
	T FirstOrDefault<T>(Expression<Func<T, bool>> predicate) where T : class, 
        IAggregateRoot, IQueryableEntity;
	T First<T>(Expression<Func<T, bool>> predicate)
        where T : class, IAggregateRoot, IQueryableEntity;
	Task<T> FirstOrDefaultAsync<T>(Expression<Func<T, bool>> predicate)
        where T : class, IAggregateRoot, IQueryableEntity;
	Task<T> FirstAsync<T>(Expression<Func<T, bool>> predicate)
        where T : class, IAggregateRoot, IQueryableEntity;
	T Find<T>(Guid id) where T : class, IAggregateRoot;
	Task<T> FindAsync<T>(Guid id) where T : class, IAggregateRoot;
	IQueryable<T> FindAll<T>()
        where T : class, IAggregateRoot, IQueryableEntity;
	Task<IList<T>> FindAllAsync<T>()
        where T : class, IAggregateRoot, IQueryableEntity;
	T Get<T>(Guid id) where T : class, IAggregateRoot;
	Task<T> GetAsync<T>(Guid id) where T : class, IAggregateRoot;
	IQueryable<T> Where<T>(Expression<Func<T, bool>> predicate)
        where T : class, IAggregateRoot, IQueryableEntity;
	void Remove<T>(T aggregate) where T : class, IAggregateRoot;
	void SaveChanges();
	Task SaveChangesAsync();
}
```

Besides the common functionality of adding and removing aggregate roots and finding them by their ID, the repository also provides method for finding them using more advanced queries. These methods are, however, defined with additional generic method constraint and can only be used with entities that implement the `IQueryableEntity` interface (this interface is empty and serves just to signify what entities can be used in those queries). For example, this means while these methods will be available for aggregate roots stored in a RDBMS and accessed via Entity Framework (generally any `BasicAggregateRoot`-derived aggregate roots), they will not be available for event sourced aggregate roots because event store usually do not possess these kinds of querying features.

Aggregate changes are automatically persisted upon saving the repository. It is unnecessary to call the save method explicitly as the repository implements a unit of work provider, which means it gets automatically saved when the unit of work is committed at the end of the command processing (unless any unhandled exceptions are thrown). The mechanism for detecting changes in the entities depends on the actual aggregate store implementation (e.g. event sourced entities are saved when they published any new uncommitted events, while changes in entities persisted by Entity Framework rely on its own internal change tracking mechanism).

#### CRUD aggregate store&#xD;

CRUD aggregate store is not tied to single specific database technology and is just a thin layer on top of ICrudRepository. CRUD data repository is the second type of repositories providing a more direct access to databases without the constraints of the domain and is in-depth discussed in chapter 5.5. All the persistence-specific features of their implementations (e.g. the mapping of entities to database) also apply to aggregates accessed via this aggregate store.

#### Event sourced aggregate store&#xD;

Similar to the CRUD aggregate store, the event sourced aggregate store is not implemented using a single specific database technology and is internally using IEventStore which is the source of the actual database connector implementation.&#x20;

### CRUD data repository

CRUD data repositories (implementations of `ICrudRepository` which is contained in Revo.DataAccess module) represent a way of a more direct way of accessing database. Unlike the aggregate repository (`IRepository`), it is not burdened with domain concepts like aggregate consistency boundaries and encapsulation and provides more flexibility when working with data. Where IRepository offered only basic functionality for working with entities to abstract from the underlying technology, `ICrudRepository` strives to do the opposite and offer maximum of the features that the used database (or an ORM) has while still maintaining some minimum level of abstraction in order to enable easy testing. Having said that, it is important to emphasize that they serve a completely different purpose – while the aggregate IRepository would usually be used on the write side of the application in command handlers to update the domain, the CRUD repository will mostly be used just for efficient access to read models in projectors and query handlers and in other places that are not encumbered by the complex business rules handled by the domain model.&#x20;

{% hint style="warning" %}
Under no circumstances it should be used to modify domain model data bypassing its business rules. However, in some scenarios, when it is unnecessary to maintain different write model and read model in the database it might be possible to reuse the domain model for queries.
{% endhint %}

The `ICrudRepository` interfaces relies heavily on the use of `IQueryable<T>` support of the .NET platform. This enables to perform arbitrary queries on the database without bloating the interface definition with a huge number of different query methods or a need for custom repositories for every specific, saving a lot of developer’s time, while still also providing type safety and the safety of compile-time checks to a certain degree.

Most of the read-related functionality of `ICrudRepository` is actually defined in a base type named `IReadRepository`. This base type does not allow any modifications to the entities (i.e. it has no save or add/remove methods), which means it is very suitable in situations when we want to limit the operations an object can do with entities in the repository – for example in a query handler that should always only performs reads of the database. It also potentially makes testing those entities easier.

Most of the CRUD repository implementations will also define its own repository interfaces derived from `ICrudRepository` in order to facilitate the use of the features specific to its technology (for example, `IEFCoreCrudRepository` making it possible to directly work with some of the EF Core ORM features).

Both types of repositories also offer an in-memory implementation of their interfaces that are suitable for testing purposes. For more information about this, see [Testing](/reference-guide/testing).

Repository filters

All repositories in Revo framework also support the concept of repository filters. Repository filters allow decorating of the behavior of repositories with cross-cutting concerns like authorization or multi-tenancy. These filters can control what entities are queried and saved by the repository. Repository filters can be registered to be implicitly enabled for all new repositories. By default, Revo currently registers two repository filters:

* tenant repository filter (see [multi-tenancy support](/reference-guide/multi-tenancy)),
* authorization repository filter (see [how to implement authorization](/reference-guide/authorization)).

## Event stores

### SQL event store&#xD;

TODO


# Database migrations

Database migrations in Revo are a simple feature how to version database schema.

## Overview

Migrations are simple SQL scripts that are applied to database anytime an upgrade is needed. Revo automatically tracks the latest version (using semantic versioning with dots, e.g. 1.2.3) of every migration module you define and if it finds a migration to newer version, it applies it (and all subsequential migrations, in order).

{% hint style="success" %}
To deal with changes in domain event definitions for events stored in an event store, you should rather look into [event upgrades](/reference-guide/events#event-upgrades). Revo database migrations described in this section are better suited to upgrade your read models.
{% endhint %}

By default, migrations are only applied automatically in debug mode (for safety reasons) and framework tries to upgrade all modules for which it finds new migrations upon the startup of the application. This can be overriden with [configuration](/reference-guide/database-migrations#configuration). Alternative way to run the migrations (e.g. in production, using CI/CD) is to use the [CLI](/reference-guide/database-migrations#cli-revo-dbmigrate).

{% hint style="info" %}
All migrations during an upgrade are always applied transactionally.
{% endhint %}

## Using migrations

### Register migrations

To automatically discover migrations in your project, add them to a folder in your project (e.g. *Sql*) and compile them as **embedded resources**. In a `NinjectModule` in your project, you can register the migrations in an assembly then like this:

```csharp
Bind<ResourceDatabaseMigrationDiscoveryAssembly>()
  .ToConstant(new ResourceDatabaseMigrationDiscoveryAssembly(GetType().Assembly, "Sql"))
  .InSingletonScope();
```

You can also specify custom migration file name regex (by default it finds all *.sql* files with names adhering to a convention) or configure auto-discovery in a local file system directory using `FileDatabaseMigrationDiscoveryPath`.

Default migration filename format is as follows:

```csharp
module-name_1.0.0_pgsql.sql
```

* Module name may contain letter, numbers and hyphen and defines the scope for versioning.
* Version (here 1.0.0) must be specified using the semantic versioning notation (i.e. both *1* or *1.2.3.4.5* are also fine). Version can be omitted if specified inside the file or if migration is repeatable.
* *pgsql* (optional) here denotes a migration tag - using tags, you can define the same migration version differently for different database systems, environments (debug/production), etc.

### Migration file headers

Besides naming the migrations files using a conventions, many migration attributes can also be specified inside the migration file itself using SQL comments at the beginnin of the SQL script.

Example:

{% code title="app-main.sql" %}

```sql
-- this is an example SQL migration
-- version: 1.1.0
-- description: Description is only informative.
-- dependency: vendor-xyz
-- dependency: app-commons@1.2.0

-- SQL migration script itself...

CREATE TABLE app_mytable (
	app_mta_mytable_id uuid PRIMARY KEY
	-- etc.
);
```

{% endcode %}

The example shows all supported header options:

* **version**: You can specify the version in the file instead of specifying it in the file name, which may be useful if you want to prevent renaming the migration file often.
* **description:** Description is only informative and gets stored in the database migration history table.
* **dependency**: A migration script can specify any number of dependency script that must be installed first before proceeding with its own execution. Dependency can also be specified with specific version (*app-commons\@1.2.0*) or to the latest module version (example of *vendor-xyz* dependency).

### Baseline migrations

Baseline migrations are optionally defined migrations that define a simplified script for creating a new schema from scratch and will only be used on empty  databases (or more precisely, if the module has no previous migration history in used database). For such cases, baseline migrations will always be preferred over regular migrations (if available). For example, this means that if we define these migrations

* *app-1.0.0.sql*
* *app-1.1.0.sql*
* *app\_baseline\_1.1.0.sql*,

and run them on an empty database, the baseline script will be used. However, if the module has previously been created using the *app-1.0.0.sql* migration script, app-1.1.0.sql will be run now (not the baseline).

Migration can be marked as baseline by including *\_baseline* after its module name in its filename, just before the version (if specified in the filename).

### Repeatable migrations

Repeatable migrations are a special kind of migrations that is not explicitly versioned and is only versioned using the checksum of its contents. Simply put, repeatable migrations are re-applied everytime their contents change.

Migration can be marked as repeatable by including *\_repeatable* after its module name in its filename and they cannot have an version explicitly specified.

### Dependencies

As shown in [migration file headers example](/reference-guide/database-migrations#migration-file-headers), migrations can also specify dependencies to other modules. A dependency to a module means that said module must be installed first before running the original migration itself. Dependencies can also be specified with specific version (e.g. *app-commons\@1.2.0*) or to the latest module version (when no version is specified).

&#x20;Dependencies may have multiple levels, Revo always tries to resolve a correct dependency tree for corresponding migration path.

## CLI (revo-dbmigrate)

Database migrations CLI allow you to run the migrations outside of the execution scope of your project. This is useful when you need to run the migration manually from a script or from CI/CD, for exaple.

You can install the CLI it as a global .NET Core tool:

```bash
dotnet tool install -g Revo.Tools.DatabaseMigrator
```

This installs the latest CLI version from NuGet. Afterwards, you can use the tool using the *revo-dbmigrate* command from anywhere. Example:

```csharp
revo-dbmigrate install -c "Server=localhost;Port=5432;Database=mydb_test;User Id=postgres;Password=" -p Npgsql -a "C:\my\project.dll" -m "app-*" "*"
```

You can either *preview* (which only shows what will be done) or *install* (which actually executes the migrations on the database). You also either need to specify the path to your project DLLs (so it can load the migrations from its embedded resources) or specify the path on disk where the SQL scripts physically reside.

You can see the full description for all available CLI commands using the --help switch:

```csharp
revo-dbmigrate --help
```

## Configuration

Database migrations can be configured when setting-up Revo application (e.g. in you Startup class).\
Besides overriding wheter to apply migrations upon application startup (on only in debug mode by default), you can also affect which modules to migrate (which can also use module name wildcards) or the target versions to upgrade to.

```csharp
return new RevoConfiguration()
    ...
    .ConfigureInfrastructure(
      cfg =>
      {
        //automatic migrations always on
        cfg.DatabaseMigrations.ApplyMigrationsUponStartup = true;
        
        //first migrate modules with name beginnin 'app-', then migrate everything
        cfg.DatabaseMigrations.MigrateOnlySpecifiedModules = new List<DatabaseMigrationSearchSpecifier>()
        {
          new DatabaseMigrationSearchSpecifier("app-*", null),
          new DatabaseMigrationSearchSpecifier("*", null)
        };
      });
```


# Projections

Projection are specialized event listeners used for materializing events published by event sourced aggregates into better usable read models.

It is a practical requirement for most applications with event sourcing to also maintain a co-existent read model for the needs of the query side of the applications (client user-interfaces, reporting, etc.). This read model will typically exist in a form of a record in another database, that we can **query easily** (e.g. a **row in a relational DBMS**). The object that takes care of creating and updating read model of a single aggregate type is called *projector* (as they project the effects of the events into some other form).

## Short example

Following sample illustrates how a projector using EF Core read model can be implemented for simple Todo aggregate.

{% tabs %}
{% tab title="TodoReadModelProjector .cs" %}

```csharp
public class TodoReadModelProjector :
  EFCoreEntityEventToPocoProjector<Todo, TodoReadModel>
{
    public TodoReadModelProjector(IEFCoreCrudRepository repository)
      : base(repository)
    {
    }

    private void Apply(IEventMessage<TodoRenamedEvent> ev)
    {
        Target.Name = ev.Event.Name;
    }
}
```

{% endtab %}

{% tab title="TodoReadModel.cs" %}

```csharp
[TablePrefix(NamespacePrefix = "TODOS", ColumnPrefix = "TDO")]
public class TodoReadModel : EntityReadModel
{
  public string Text { get; set; }
}
```

{% endtab %}

{% tab title="Todo.cs" %}

```csharp
[DomainClassId("D8A1F0C6-CD0A-4F66-8181-336AAFE11248")]
public class Todo : EventSourcedAggregateRoot
{
    /** CODE OMITTED FOR BREVITY **/

    public string Name { get; private set; }
    
    public void Rename(string name)
    {
        if (Name != name)
        {
            Publish(new TodoRenamedEvent(name));
        }
    }
    
    private void Apply(TodoRenamedEvent ev)
    {
        Name = ev.Name;
    }
}
```

{% endtab %}

{% tab title="TodoRenamedEvent.cs" %}

```
public class TodoRenamedEvent : DomainAggregateEvent
{
    public TodoRenamedEvent(string name)
    {
        Name = name;
    }

    public string Name { get; }
}
```

{% endtab %}
{% endtabs %}

## Basics

You can easily define a projector by implementing a generic interface specific to used data persistence provider and specifying the projected aggregate type as one of its generic parameters. By default, these projectors are auto-discovered and registered upon application startup.

{% hint style="info" %}
A projector class always projects events of a single aggregate type.
{% endhint %}

Every persistence provider also offers a few convenience base classes that implement features like versioning with optimistic-concurrency or automatic creating of POCO read models.

### Entity event projectors

Any projector derived from `EntityEventProjector` (which are all convenience projector base classes provided by Revo) will use a convention to look for methods on the projector class which will be called for individual events projected.

These methods should have any of the following signatures:

```csharp
void Apply(IEventMessage<TEvent> ev);
Task Apply(IEventMessage<TEvent> ev);
void Apply(IEventMessage<TEvent> ev, Guid aggregateId);
Task Apply(IEventMessage<TEvent> ev, Guid aggregateId);
void Apply(IEventMessage<TEvent> ev, Guid aggregateId, TTarget target);
Task Apply(IEventMessage<TEvent> ev, Guid aggregateId, TTarget target);
```

(with `TEvent` being the event class and `TTarget` being the read model class).

### POCO (CRUD) read model projectors

A POCO projector is a CRUD (create/read/update/delete) repository-backed event projector for an aggregate type with a single POCO read model object (row) for every aggregate.

On top of the Apply-method convention, POCO read model projectors (derived from`EntityEventToPocoProjector<TSource, TTarget>`) also

* Automatically creates, loads and saves read model instances using the repository based on aggregate ID,
* If read model class is `IManuallyRowVersioned`, automatically handles read model versioning and projection idempotency using event sequence numbers,
* Automatically sets read model IDs for read model that is `IEntityReadModel`,\
  class IDs for `IClassEntityReadModel` and tenant IDs for `ITenantReadModel`.

### Read model base clases

Because many projections will want to work with a simple object (POCO) representation of the read model, the framework also defines a stub base classes for these projection implementations. This is convenient when using object-relation mapping libraries (ORM), for example.

* If the read model class implements `IEntityReadModel` (e.g. the predefined `EntityReadModel` base class), the projector automatically injects the Id property based on the aggregate ID.
* If the read model class implements `IClassEntityReadModel` (e.g. the predefined `ClassEntityReadModel` base class), the projector automatically injects the ClassId property based on the aggregate class ID metadata from the event or from the `DomainClassIdAttribute` of the aggregate class itself (used as a fallback).
* If the read model class implements `ITenantReadModel` (e.g. the predefined `TenantEntityReadModel` base class), the projector automatically injects the `TenantId` property based on the ID specified in TenantAggregateRootCreated (which is automatically emitted by the `TenantEventSourcedAggregateRoot` upon its creation).

## Providers

### EF Core

EF Core persistence provider automatically discovers projectors implementing:

* `IEFCoreSyncEntityEventProjector<TSource>`
  * `EFCoreSyncEntityEventToPocoProjector<TSource, TTarget>` for POCO read models
  * `EFCoreSyncEntityEventProjector<TSource>` for arbitrary read models
* `IEFCoreEntityEventProjector<TSource>`
  * `EFCoreEntityEventToPocoProjector<TSource, TTarget>` for POCO read models
  * `EFCoreEntityEventProjector<TSource>` for arbitrary read models

{% hint style="success" %}
As you can see, EF Core provider also supports **synchronous variants** for all projector interfaces, which are then (opposed to the normal projectors) run inside single database transaction as saving the aggregate itself (as well as queueing asynchronous events, etc.). This usually leads to **better performance** if you need to wait for the projections anyway (on the other hand, if you don't and/or are doing heavy computations in the projector, you may be better off with asynchronous versions).
{% endhint %}

### Entity Framework 6

EF6 persistence provider automatically discovers projectors implementing:

`IEF6EntityEventProjector<TSource>`

* `EF6EntityEventToPocoProjector<TSource, TTarget>` for POCO read models
* `EF6EntityEventProjector<TSource>` for arbitrary read models

### RavenDB

RavenDB persistence provider automatically discovers projectors implementing:

`IRavenEntityEventProjector<TSource>`

* `RavenEntityEventToPocoProjector<TSource, TTarget>` for POCO read models
* `RavenEntityEventProjector<TSource>` for arbitrary read models

## Background technical details

The framework offers a number of facilities to work with projections and read models. For their operation, they expect a sequence of individual domain events on the input and return a data structure that is better usable for the read side model on the output. At its very core, projections are just conveniently set-up asynchronous event listeners – despite possibly hiding some of their internal complexity at a first glance thanks to the infrastructure provided by the framework. The facilities for read model projection consist of several parts. At the most basic level, it is possible to define entity event projector for a specific aggregate type by simply implementing `IEntityEventProjector` interface and registering it with the framework.

These projectors are always strictly bound to projecting events of single aggregate type – however, it is possible to define many projectors for one aggregate type. The contract of this interface is designed in a simple fashion – whenever the projection manager receives new events from the event bus, it sorts them based on the aggregate ID. Later, when the reading from an event queue gets finished, it starts to iterate through the aggregate and loading the one-by-one from the corresponding repository aggregate stores. By looking up the class ID of every aggregate, it then decides which projectors to invoke for every aggregate and its events. When the projections finish, the projection manager commits all of the registered projectors. This ensures that the projections are executed in an efficient manner, always with a complete batch of events coming from a finished unit of work.

{% hint style="info" %}
The batching of events by their source aggregates also clearly defines the scope and the lifetime of every projector, making it possible to apply several optimizations in the event projection process. However, it also requires that for creating projections combined from events of two or more aggregates (or aggregate types), it is necessary to create corresponding number of separate projectors (all of them working on the same read model). This is a certain compromise that was made in order to keep the framework architecture simpler and cleaner. Nevertheless, while it might seem to be something that makes writing these extra projections unnecessarily verbose, it makes sense from the perspective of write side consistency. Put it other words, because it is the aggregates themselves that define (in terms of DDD) the consistency boundaries, implying the system will always be modifying an aggregate at a time, the projectors will always receive events in batches corresponding to those aggregate modifications. Using the same reasoning, because the modifications of two different aggregates will always be independent and only eventually-consistent, any attempt of immediate consistency of read models across two or more aggregate would only be fictitious and in reality, unattainable.
{% endhint %}


# Authorization

Authorization is one of the most common cross-cutting concerns that most applications need to deal with. Revo framework addresses this by providing a number of facilities for it.

## Permissions

### Defining permissions&#xD;

The framework works with a simple and flexible concept of permissions. A permission defines the authorization to perform a certain action, optionally (if specified) on a specified resource or/and in a specified context. The types of these actions (e.g. “edit blog post”) are defined as `PermissionType`s in so called permission catalogs and are identified by their name and a GUID:

```csharp
[PermissionTypeCatalog("Revo.Infrastructure.Notifications.Channels.Apns")]
public static class Permissions
{
	public const string RegisterDeviceToken =
        "{EAA3FA48-1227-4479-969D-D48505335844}";
	public const string DeregisterDeviceToken =
        "{0F47EDC4-55C4-42E8-8F32-63C9BAE06181}";
	public const string PushExternalNotification =
        "{2A88944A-16F6-494F-8867-33CBD535C1E5}";
}
```

These permission catalog classes need to be static and decorated with the `PermissionTypeCatalogAttribute` that specifies the namespace of the permission catalog. Individual public constant string fields in the class then define the actual permission types in it (field name is used as the permission name that is appended to the catalog namespace).

An entity (e.g. a user) can possess a permission by creating an instance of `Permission` class which defines the actual ownership of a permission type (“create a blogpost in a category”) on a certain resource (e.g. ID of the category) and within a certain context (e.g. “german section of the website”). Both resource and context can also be null meaning a universal permission (i.e. for all resources and within all contexts; also, the concept of resources and/or contexts may not necessarily be applicable to all permission types where it does not make sense).

These `Permission`s will usually be attached to user roles, groups or individual users – this is, however, completely up to the implementation of the end applications using the framework and will usually depend on the business logic of the application. This gap between the application-specific implementation of users and permission is bridged by an implementation of `IUserContext` which resolves the user and his permission in the context of the current request. For the web ASP.NET platform, this is implemented by the framework by the Revo.Platforms.AspNet package whose implementation is backed by the enterprise-grade ASP.NET Identity framework developed by Microsoft that can be easily plugged with many authentication providers (e.g. local database, OAuth, etc.) and already contains the implementations for many common scenarios (e.g. user management, user roles, etc.).

Besides the possibility to use this user context manually for authorization (e.g. in API controllers or command handlers), it is also possible to use some of the framework infrastructure to make this easier (see following chapters).

### Command permissions

Using the concept of permissions, it is possible to decorate commands and queries with attributes that will require them to be authorized before their actual execution. This is implemented using command filters (see chapter 7.4.2) and is enabled by default. To define an authorization rule for a command, decorate its class with an `AuthorizePermissionsAttribut`e:

```csharp
[AuthorizePermissions(Permissions.PushExternalNotification)]
```

The attribute argument can refer to a number of permission type GUIDs defined in a references permission catalog (here, the `Permissions` class).

An alternative way for command authorization making it also possible to employ a custom command-authorization logic is to implement an `IPreCommandFilter<T>` (possibly in the form of a `CommandAuthorizer<T>`).

## Entity query filters

It is sometimes necessary to apply authorization rules in a different way – not specifying that a user can perform a certain action, but rather affecting what portion of data (e.g. what rows in database) he sees. To achieve this in a non-intrusive, aspect-oriented way, framework implements a concept of entity query filters. The entity query authorizer then takes a queryable collection and the current command as an input and returns a filtered (i.e. with authorization rule filtering applied) on the output, for example:

```csharp
IQueryable<Order> orders = await readRepository.FindAll<Order>()
    .Where(x => x.Status == OrderStatus.Pending)
    .AuthorizeAsync(command);
List<Order> orderList = await orders.ToListAsync();
```

The `orderList` will now contain list of pending orders filtered according to the registered system-wide rules for order authorization. It is also possible to authorize according to a nested entity, e.g. if authorization based on the customer who sent the order was needed instead:

```csharp
IQueryable<Order> orders = await readRepository.FindAll<Order>()
    .AuthorizeAsync(command, x => x.Customer);
```

The actual authorization rules are defined by implementing `IEntityQueryFilter<T>` interface (where `T` denotes the type of the entity authorized) and registering its instances in the dependency container. The `FilterAsync` method returns a filtering expression that is applied to the queryable object, for example:

```csharp
public class OrderQueryFilter : IEntityQueryFilter<Order>
{
	private readonly IUserContext userContext;
 
    ...
	
	public async Task<Expression<Func<Order, bool>>> FilterAsync(
		ICommandBase query)
	{
		return x => x.Customer.Id == userContext.UserId;
	}
	
	...	
}
```

(some parts omitted for brevity).


# Validation

## Command validation

Commands will often come from external untrusted sources, such as APIs publicly exposed to the internet. For that reason, it will often be necessary to do some sanity and integrity checks making sure their data are valid before proceeding to their further processing. As this will usually be considered a cross-cutting concern (like authorization) rather independent of the business logic processing the command, the framework implements a pre-command validation filter (which is enabled by default for all commands). Any incoming command will automatically be validated using the .NET’s integrated `System.ComponentModel.DataAnnotations.Validator`. This makes it easy to apply arbitrary validation rules using the existing validation attributes infrastructure.

Example:

```csharp
public class AddClassifiedAdCommand : ICommand
{
	[Range(0, decimal.PositiveInfinity)]
	public decimal Price { get; set; }

	[Required]
	public string AdvertismentText { get; set; }
	
	[Required]
	public string PhoneNumber { get; set; }
}
```


# Request life-cycle

## Overview

In Revo, a typical processing of a request consists of several distinct phases. A simplified overview of the data flows during a request can be seen in picture below.

{% hint style="danger" %}
This section is outdated and needs rewriting.
{% endhint %}

![Data flows during a request](/files/-LByzFmEkQ-sPWrmvA6u)

## Command handlers

A processing of a request can be initiated in different ways – most often by an HTTP request received by a controller of a server API (e.g. implemented with ASP.NET WebAPI) or by a message received from an external service via an integration layer (e.g. Rebus messaging via RabbitMQ). Such request would usually trigger the processing of a command or a query. In case of a REST API request, the controller would construct a command or query based on data received from the client and send it to the *command bus*. Command bus finds a handler responsible for the command or query type. Note that if an integration layer like Rebus is configured, it is also possible that the command bus will directly hand over the processing of this command/query to an external service like depicted by the diagram.

When a local handler is about to get invoked, the command/query goes through the configured processing pipeline as described in chapter. By default, this includes the use of a number of command filters implementing various cross-cutting concerns like authorization and validation. Very importantly, it also includes the automatic management of the *unit of work*.

## Unit of work

A new unit of work is automatically started when a command (implementing `ICommand`) is processed. On the other hand, queries (implementing `IQuery<T>`) do not start a unit of work as they should not modify the domain data (which means they do not need a unit of work) a this paragraph is irrelevant to their processing. The unit of work wraps the effects of a single business transaction defined by the command. When the command handler finishes, the unit of work is automatically committed, or it is canceled when the command handler fails with an exception. The unit of work commits all of its providers – i.e. most importantly, the repository. Thanks to this, it is not necessary (or desirable) to manually save the repository within the command handler.

Committing a repository causes that all new (unpublished) events from its saved aggregates get pushed to the event buffer of the current unit of work. Later, when the committing of a repository finishes, the unit of work publishes all the events queued in the event buffer. This causes the invocation of all registered synchronous event handlers, which still happens in the scope of the original request (i.e. as a blocking operation, possibly on the same thread). During this phase, the event is also dispatched to the queues of all registered asynchronous event listeners (by invoking their event sequencers). When the dispatching is done, the unit of work tries to pseudo-synchronously process those of the listeners who signaled `ShouldAttemptSynchronousDispatch` (as previously explained in [chapter describing event processing](/reference-guide/events#pseudo-synchronous-event-dispatch)). This makes is possible to work with the listeners (e.g. projections) like if they were actually processed synchronously, while still retaining the reliability of asynchronous event delivery. When these listeners complete, the unit of work schedules the background execution of the remaining listeners, which ends its life.

### Object life-time during a request

TODO


# Sagas

## Overview

Sagas implement a way of coordination of long-running processes and collaboration between eventually consistent aggregates. To do that, they listen for published domain events and send out new commands.

{% hint style="info" %}
Sagas in Revo framework are implemented as stateful process managers similarly to some other frameworks.
{% endhint %}

## Basic usage with saga keys

By default, the two predefined saga base classes (`BasicSaga` and `EventSourcedSaga`, based on different persistence mechanisms as explained below) use a convention-based mapping for their registration and event handling. Events can be handled with  void `Handle(IEventMessage<TEvent> ev)` methods that take a single argument of type `IEventMessage<TEvent>` where `TEvent` is the specific type of event to handle (its subtypes will not be matched). These methods need to be decorated with a `SagaMethodAttribute` that specifies how the saga instances should be located. An example:

```csharp
[SagaMethod(SagaKey = "UserId", EventKey = "AggregateId")]
private void Handle(
    IEventMessage<UserVerificationTimeoutExiredEvent> ev)
{
    if (!IsUserVerified)
    {
        Send(new CancelUserRegistrationCommand(UserId));
        End();
    }
}
```

These methods can have any access modifier (but private is usually preferred). For sagas that implement `IConventionBasedSaga` (applies for both mentioned saga base classes), this also means they will be automatically registered in the saga registry for the event types they implement if they are found in any of the referenced assemblies during the startup, so they are invoked when a saga event dispatch happens.

### Saga method binding

The `SagaMethodAttribute` specifies what saga instances should the event be sent to. There are currently five options available:

* Always start a new saga when the event happens.

```csharp
[SagaEvent(IsAlwaysStarting = true)]
```

* Find all existing sagas.

```csharp
[SagaEvent]
```

* Find all existing sagas **and** start a new one if none were found.

```csharp
[SagaEvent(IsStartingIfSagaNotFound = true)]
```

* Find existing sagas by correlating a property of the event and a saga key.

```csharp
[SagaEvent(SagaKey = "Foo", EventKey = "Bar")]
```

* Find existing sagas by correlating a property of the event and a saga key and start a new one if none were found.

```csharp
[SagaEvent(SagaKey = "Foo", EventKey = "Bar", IsStartingIfSagaNotFound = true)]
```

The saga correlation keys need to be previously set by the saga itself using methods like `AddSagaKey`/`SetSagaKey`. Sagas can save multiple values for one key, allowing it to react to any of events correlated to them. It is also possible to specify multiple `SagaEventAttributes` for one method.

### Sending commands

Because sagas should not have any external side effects just like regular aggregates and by default, the framework will not inject any dependencies into them, they have only one primary means of communication with the outside world – sending commands and publishing events. Commands sent using `Send` method are queued and get actually processed by the command bus upon committing and saving the saga (which happens automatically when saga event processing is finished).

```csharp
Send(new CancelUserRegistrationCommand(UserId));
```

&#x20;If the processing of any of the commands fail, the saga state is not saved, and the handling of the saga will be retried later. For this reason, it is vital that the commands are idempotent in their effect, because they may get sent more than once in case of such failure. Sagas will often want to schedule the commands for processing at a later time or simply to enqueue them for a processing in a background worker queue (asyn-chronously of their processing) – this can easily be achieved using job commands. For more on this topic, please see chapter on [Jobs](/reference-guide/jobs).

### Saga state and metadata

Sagas can also have their own state. This state will be persisted in the same way as with aggregates (i.e. persisting state of `BasicSaga`s and persisting event stream of `EventSourcedSaga`s), because the system also internally uses the regular IRepository.

{% hint style="warning" %}
Saga metadata (such as the keys and class IDs) are stored independently of the sagas in an ISagaMetadataRepository (these two operations are not atomic and are carried out in order first saga data, then saga metadata; this also means that the sagas need to count with the possibility that their metadata are not up-to-date and synchronized with their state and that the processing of an event will be retried).
{% endhint %}


# Jobs

## Overview

The framework provides a support for jobs that would be executed in background, optionally at a later point in time. This concept was previously discussed in chapter 6.6.2. Execution “in background” means asynchronously to the current executing thread (i.e. so it does not block the HTTP request currently processed, for example).

### Job scheduler

The interface `IJobScheduler` provides a gateway to working with the jobs scheduler and offers a way to enqueue a job for immediate execution in background (as soon the machine has the capacity to do so, e.g. when it is limited to process only limited amount of jobs in parallel) or to schedule a job for execution at a specific date and time (again started automatically in background). It is also possible to delete a previously enqueued/schedule job (if it has not already been processed).&#x20;

### Jobs and job handlers

Jobs work in a way very similar to commands: it is possible to define job types by implementing the `IJob` interface (which itself is empty). For every job type needs to be a job han-dler registered in the dependency container. The job handler interface looks like this:

```csharp
public interface IJobHandler<in T>
	where T : IJob
{
	Task HandleAsync(T job, CancellationToken cancellationToken);
}
```

The job handler is responsible for the actual execution of a job.

There is an out-of-the-box support for `ExecuteCommandJob` which simply executes any com-mand specified. Moreover, there are `EnqueueJobCommand` and `ScheduleJobCommand` commands that on the other hand allow enqueuing and scheduling of jobs simply using a command. This is especially useful when used in conjunction with saga that can only produce commands to perform any side-effects.

## Hangfire

For a reliable execution of jobs, the framework can use the [Hangfire ](https://www.hangfire.io/)library. Hangfire also takes care of job failure management (restarting the jobs when they fail, if configured to do so), offers a web administration console and handles back-ground execution in ASP.NET (Core) applications well (so their application pools are not recycled prematurely).

To use Hangfire, add reference to **Revo.Hangfire** package and configure it when setting up your Revo application (e.g. in your Startup class) as follows:

```csharp
return new RevoConfiguration()
    ...
    //or use any other Hangfire storage provider
    .UseHangfire(() => new PostgreSqlStorage(dbConnectionString));
```


# Messaging and integrations

Scale and integrate by publishing and receiving events, commands and queries using common messaging patterns, e.g. with RabbitMQ message queue (using EasyNetQ connector or Rebus service bus).

## RabbitMQ messaging with EasyNetQ

[EasyNetQ ](http://easynetq.com/)is an easy-to-use library for communication with the popular open-source [RabbitMQ](https://www.rabbitmq.com/) message broker. Using the **Revo.EasyNetQ** package, you should be able to implement simple messaging patterns in a Revo application in a matter of minutes.

Currently, the EasyNetQ package support only publishing and subscribing to events.\
An example configuration follows:

```csharp
new RevoConfiguration()
    ...
    .UseEasyNetQ(true, new EasyNetQConnectionConfiguration("host=localhost"),
        subscriptions => subscriptions.AddType<ExternalIntegrationEvent>("MyApp.Integration.Machine0"),
        advancedAction: cfg => cfg.EventTransports.AddType<MyAppIntegrationEvent>())
    ...;
```

This configuration connects to a RabbitMQ server on localhost (see the [EasyNetQ connection string formats](https://github.com/EasyNetQ/EasyNetQ/wiki/Connecting-to-RabbitMQ) for reference) and subscribes to a single event (base) type `ExternalIntegrationEvent`  using the specified subscriber ID. Anytime a new event is received from a corresponding (as per EasyNetQ configuration) RabbitMQ queue(s), the event is propagated inside the Revo application to all its registered `IEventListener<T>` listeners (see [event listener registration](/reference-guide/events#register-the-event-listener)).

Furthermore, it also registers an event transport for an event (base) type `MyAppIntegrationEvent`. Anytime this event type (or its derived type) is published on the `IEventBus`, the Revo also automatically publishes the event to the RabbitMQ (in this case, to the default message exchange configured by EasyNetQ).

## Rebus service bus integration

[Rebus](https://github.com/rebus-org/Rebus) is a simple and lean service bus implemented in .NET. Out-of-the-box, Revo currently offers only a limited and experimental support for its integration (*.NET 4.7.1+ only*). For simpler, but production-ready messaging integration, you can use the aforementioned [RabbitMQ connector](/reference-guide/integrations#rabbitmq-messaging-with-easynetq) implemented using EasyNetQ library.

When using the **Revo.Rebus** module, the framework automatically hooks with&#x20;the command and event bus. The connection parameters for the RabbitMQ message queue can be specified in default application configuration (either via **app.config** or **Web.config** file) in form of a connection string defining the server URL to connect to and the input queue to subscribe to, e.g.:

```
<connectionStrings><add name="RabbitMQ" connectionString=
"Url=amqp://guest:guest@localhost:5672;InputQueue=Revo" /></connectionStrings>
```

Using this integration, the application is able to deliver events to other services connected to the same exchange and also receive the events published by those services to them. Further-more, it also makes it possible to offload some of the command and query handling to exter-nal services. As long as the system is configured to route a command or query type to an external exchange, it will always prefer the external transport over the use of local command handler (if there are registered any).

The use of this integrations is especially useful when building application using a micro-service architecture. For queries, it is also possible to use worker queues, effectively scaling the load of their processing to multiple query service instances.


# Multi-tenancy

## Multi-tenancy environments

With the rising popularity of cloud software deployment and the software-as-a-service (SaaS) model, it is a very common requirement that multiple instances of a single application (e.g. multiple customers with separate environments) should be able to run on a single infrastructure node (one webserver, for example) or using shared resources (e.g. single database for a greater number of customers). To be able to abstract from these concepts when developing an application (which would usually make the application logic much more complicated), the framework provides support for basic multi-tenancy support. Multi-tenant application is an application that is able to host multiple independent application instances in one single running instance of the system. In this terminology, a tenant is the unit that separates individual instances among themselves – i.e. it would be quite customary that each customer would also be a tenant. There are several facilities available to help with that.

## Tenant context

### Context resolver

The framework defines an `ITenantContextResolver` which is responsible for resolving the tenant that is active for the scope of an active request. By default, the framework uses `NullTenantContextResolver` which always resolves to a null tenant. It is also possible that certain parts of the application will have null tenant (e.g. the login pages) and some will actually resolve to a specific tenant (i.e. the rest of the application). The framework defines one more tenant context resolver – `SingleTenantContextResolver` which always resolver to a specific (constant-value) tenant. This is especially helpful during development (rather than in a production environment). Production-envionment applications are free to implement and register their own implementations of tenant context resolver – very commonly resolving by the HTTP request subdomain, request authorization or any other request-dependent properties. The resolvers return objects of the `ITenant` interface which simply contain just an ID and a name property and can be implemented in any way they need.

```csharp
public interface ITenantContextResolver
{
    ITenant ResolveTenant();
}
```

### Tenant context

The tenant context is useful for a number of reasons.

```csharp
public interface ITenantContext
{
    ITenant Tenant { get; }
}
```

Besides the option to manually work with it using `ITenantContext`, the framework implements a repository filter (enabled by default for all repositories) that automatically filters the returned and added or modified repository records by their `TenantId` provided they implement the `ITenantOwned` interface.&#x20;

```csharp
public interface ITenantOwned
{
    Guid? TenantId { get; }
}
```

Within any tenant context, the repository allows working with any records that belong to that specific tenant and records that have null tenant specified (and throws an exception if the repository tries to modify records it should not). By default, null tenant context has only access to records having null tenant ID. This enables an automatic workflow when working with any tenant-owned entities that prevents the risk of leaking unauthorized access to records of other tenants.

## Configuration

Multi-tenancy features can be configured when setting-up Revo application, e.g. in you Startup class:

```csharp
return new RevoConfiguration()
    ...
    .ConfigureInfrastructure(
      cfg =>
      {
        cfg.Tenancy.UseNullTenantContextResolver = false;// now you can bind your own tenant context resolver
        cfg.Tenancy.EnableTenantRepositoryFilter = true; // by default
        // more...
      });
```


# Testing

## In-memory persistence

To make developer's life easier and encourage the test-driven development approach, Revo features a few helpers for testing of domain models and other parts of the application.

### InMemoryCrudRepository / EF6InMemoryCrudRepository&#xD;

In-memory CRUD repository makes it possible test any components that persist data to a database with a regular CRUD repository. This in-memory version implements nearly all of the features of its “real” counterparts (like the EF6) with the exception of multi-key IDs. Furthermore, the `EF6InMemoryCrudRepository` implements the additional features of EF6 (like the methods `Entries()`/`Entry<T>(T)` for features like explicit lazy-loading and other) and by emulating its queryable providers, it makes it possible to seamlessly use the asynchronous `IQueryable<T>` extension methods defined by it, e.g. `ToListAsync()` and others.

### FakeRepository&#xD;

Similar to the in-memory CRUD repository, `FakeRepository` implements the domain aggregate `IRepository` without any actual database dependencies, making it suitable for testing purposes.

## Domain model testing

To make testing of event-sourced entities less verbose and correctly test of all its aspects, i.e. not just the emission of new events and possibly a change in the public entity state, but also the fact that the entity is able to deserialize back to that state again when replaying the events from the database, the framework defines a few extension methods.

### EventSourcedEntityTestingHelpers&#xD;

Method `AssertEvents` asserts that given an initial object state and an action performed, it publishes an array of specified events and possibly also asserts the final state of the object with a custom function. If loadEventsOnly is specified true, it only replays the events specified and verifies the final state.

```csharp
static void AssertEvents<T>(this T aggregate, Action<T> action,
    Action<T> stateAssertion, bool loadEventsOnly,
    params DomainAggregateEvent[] expectedEvents)
where T : EventSourcedAggregateRoot;

static void AssertAllEvents<T>(this T aggregate, Action<T> action,
    Action<T> stateAssertion, bool loadEventsOnly,
    params DomainAggregateEvent[] expectedEvents)
where T : EventSourcedAggregateRoot;

static void AssertConstructorEvents<T>(this T aggregate,
	Action<T> stateAssertion, bool loadEventsOnly,
	params DomainAggregateEvent[] expectedEvents)
where T : EventSourcedAggregateRoot;
```

Example using xUnit test framework:

```csharp
[Theory]
[InlineData(false)]
[InlineData(true)]
public void UpdateDetails(bool loadEventsOnly)
{
	var user = new User(
        Guid.Parse("36418768-498B-47B2-BDE0-4165EAE7E5F7"),
        "original@email");

	sut.AssertEvents(
		x =>
		{
			x.UpdateEmailAddress("new@email");
		},
		x =>
	{
		x.EmailAddress.Should().Be("new@email");
	}, loadEventsOnly,
	new UserEmailUpdatedEvent("new@email"));
}
```

`AssertAllEvents` has the same call signature, but it asserts all of the uncommitted events that the entity contains and not just the events that were published after calling the action. The last variant, `AssertConstructorEvents`, does not take an action parameter, making it suitable for testing the state (and events) of newly constructed entities.


