Merge pull request #357 from meysamhadeli/docs/update-aspir-docs

docs/update aspir docs
This commit is contained in:
Meysam Hadeli 2025-07-23 16:28:40 +03:30 committed by GitHub
commit 44e408258f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
415 changed files with 456 additions and 506 deletions

120
README.md
View File

@ -1,23 +1,20 @@
# 🛩️ Booking Monolith
<div align="center" style="margin-bottom:20px">
<img src="assets/logo.png" alt="booking-microservices" />
<div align="center">
<a href="https://github.com/meysamhadeli/booking-microservices/actions/workflows/ci.yml"><img alt="ci-status" src="https://github.com/meysamhadeli/booking-microservices/actions/workflows/ci.yml/badge.svg?branch=main&style=flat-square"/></a>
<a href="https://github.com/meysamhadeli/booking-microservices/blob/main/LICENSE"><img alt="build-status" src="https://img.shields.io/github/license/meysamhadeli/booking-microservices?color=%234275f5&style=flat-square"/></a>
<div align="left">
<a href="https://github.com/meysamhadeli/booking-monolith/actions/workflows/ci.yml"><img alt="build-status" src="https://github.com/meysamhadeli/booking-monolith/actions/workflows/ci.yml/badge.svg?branch=main&style=flat-square"/></a>
<a href="https://github.com/meysamhadeli/booking-monolith/blob/main/LICENSE"><img alt="build-status" src="https://img.shields.io/github/license/meysamhadeli/booking-monolith?color=%234275f5&style=flat-square"/></a>
</div>
</div>
> 🚀 **A practical microservices with the latest technologies and architecture like Vertical Slice Architecture, Event Sourcing, CQRS, DDD, gRpc, MongoDB, RabbitMq and Masstransit in .Net 9.**
> 🚀 **A practical Monolith architecture with the latest technologies and architectures like Vertical Slice Architecture, Event Driven Architecture, CQRS, DDD and Aspire in .Net 9.**
## You can find other version of this project here:
- [Booking with Microservices Architecture](https://github.com/meysamhadeli/booking-microservices)
- [Booking with Modular Monolith Architecture](https://github.com/meysamhadeli/booking-modular-monolith)
- [Booking with Monolith Architecture](https://github.com/meysamhadeli/booking-monolith)
<div>
<a href="https://gitpod.io/#https://github.com/meysamhadeli/booking-microservices"><img alt="Open in Gitpod" src="https://gitpod.io/button/open-in-gitpod.svg"/></a>
</div>
<div>
<a href='https://codespaces.new/meysamhadeli/booking-microservices?quickstart=1'><img alt='Open in GitHub Codespaces' src='https://github.com/codespaces/badge.svg'></a>
</div>
<a href="https://gitpod.io/#https://github.com/meysamhadeli/booking-monolith"><img alt="Open in Gitpod" src="https://gitpod.io/button/open-in-gitpod.svg"/></a>
# Table of Contents
@ -26,17 +23,15 @@
- [Key Features](#key-features)
- [When to Use](#when-to-use)
- [Challenges](#challenges)
- [The Domain and Bounded Context - Service Boundary](#the-domain-and-bounded-context---service-boundary)
- [The Domain and Bounded Context](#the-domain-and-bounded-context)
- [Structure of Project](#structure-of-project)
- [Development Setup](#development-setup)
- [Dotnet Tools Packages](#dotnet-tools-packages)
- [Husky](#husky)
- [Upgrade Nuget Packages](#upgrade-nuget-packages)
- [Dotnet Tools Packages](#dotnet-tools-packages)
- [Husky](#husky)
- [Upgrade Nuget Packages](#upgrade-nuget-packages)
- [How to Run](#how-to-run)
- [Config Certificate](#config-certificate)
- [Aspire](#aspire)
- [Docker Compose](#docker-compose)
- [Kubernetes](#kubernetes)
- [Build](#build)
- [Run](#run)
- [Test](#test)
@ -49,12 +44,11 @@
- :sparkle: Using `Vertical Slice Architecture` for `architecture` level.
- :sparkle: Using `Domain Driven Design (DDD)` to implement all `business logic`.
- :sparkle: Using `Rabbitmq` on top of `Masstransit` for `Event Driven Architecture`.
- :sparkle: Using `gRPC` for `internal communication`.
- :sparkle: Using `CQRS` implementation with `MediatR` library.
- :sparkle: Using `Postgres` for `write side` database.
- :sparkle: Using `InMemory Broker` on top of `Masstransit` for `Event Driven Architecture`.
- :sparkle: Using `MongoDB` for `read side` database.
- :sparkle: Using `Event Store` for `write side` of Booking Microservice/Module to store all `historical change` of aggregate.
- :sparkle: Using `Event Store` for `write side` of Booking to store all `historical change` of aggregate.
- :sparkle: Using `Inbox Pattern` for ensuring message idempotency for receiver and `Exactly once Delivery`.
- :sparkle: Using `Outbox Pattern` for ensuring no message is lost and there is at `At Least One Delivery`.
- :sparkle: Using `Unit Testing` for testing small units and mocking our dependencies with `Nsubstitute`.
@ -68,11 +62,7 @@
- :sparkle: Using `OpenTelemetry` for distributed tracing on top of `Jaeger`.
- :sparkle: Using `OpenTelemetry` for monitoring on top of `Prometheus` and `Grafana`.
- :sparkle: Using `IdentityServer` for authentication and authorization base on `OpenID-Connect` and `OAuth2`.
- :sparkle: Using `Yarp` as a microservices `gateway`.
- :sparkle: Using `Kubernetes` to achieve efficient `scaling` and ensure `high availability` for each of our microservices.
- :sparkle: Using `Nginx Ingress Controller` for `load balancing` between our microservices top of `Kubernetes`.
- :sparkle: Using `cert-manager` to Configure `TLS` in `kubernetes cluster`.
- :sparkle: Using `Aspire` for `service discovery`, `observability`, and `local orchestration` of microservices.
## Technologies - Libraries
@ -95,48 +85,46 @@
- ✔️ **[`Hellang.Middleware.ProblemDetails`](https://github.com/khellang/Middleware/tree/master/src/ProblemDetails)** - A middleware for handling exception in .Net Core.
- ✔️ **[`NewId`](https://github.com/phatboyg/NewId)** - NewId can be used as an embedded unique ID generator that produces 128 bit (16 bytes) sequential IDs.
- ✔️ **[`Yarp`](https://github.com/microsoft/reverse-proxy)** - Reverse proxy toolkit for building fast proxy servers in .NET.
- ✔️ **[`Tye`](https://github.com/dotnet/tye)** - Developer tool that makes developing, testing, and deploying microservices and distributed applications easier.
- ✔️ **[`gRPC-dotnet`](https://github.com/grpc/grpc-dotnet)** - gRPC functionality for .NET.
- ✔️ **[`EventStore`](https://github.com/EventStore/EventStore)** - The open-source, functional database with Complex Event Processing.
- ✔️ **[`MongoDB.Driver`](https://github.com/mongodb/mongo-csharp-driver)** - .NET Driver for MongoDB.
- ✔️ **[`xUnit.net`](https://github.com/xunit/xunit)** - A free, open source, community-focused unit testing tool for the .NET Framework.
- ✔️ **[`Respawn`](https://github.com/jbogard/Respawn)** - Respawn is a small utility to help in resetting test databases to a clean state.
- ✔️ **[`Testcontainers`](https://github.com/testcontainers/testcontainers-dotnet)** - Testcontainers for .NET is a library to support tests with throwaway instances of Docker containers.
- ✔️ **[`K6`](https://github.com/grafana/k6)** - Modern load testing for developers and testers in the DevOps era.
- ✔️ **[`Aspire`](https://github.com/dotnet/aspire)** - .NET stack for building and orchestrating observable, distributed cloud-native applications.
## Key Features
1. **Independent Services**: Each service is a separate project with its own database and deployment pipeline, enabling independent development and deployment.
2. **Decentralized Communication**: Services communicate via APIs (REST, gRPC) or message brokers (RabbitMQ, Kafka), ensuring loose coupling and resilience.
3. **Scalability**: Services can be scaled independently based on demand, allowing efficient resource utilization.
4. **Fault Tolerance**: Failures are isolated, preventing cascading failures and ensuring high availability.
5. **Technology Agnostic**: Services can use different technologies, frameworks, or databases, providing flexibility.
1. **Single Codebase**: All components (UI, business logic, data access) are part of one project.
2. **Tight Coupling**: Components are highly dependent on each other, making changes riskier.
3. **Simple Deployment**: The entire application is deployed as a single unit.
4. **Centralized Database**: Typically uses a single database for all data storage and access.
## When to Use
1. **Large and Complex Projects**: Ideal for applications with complex business logic that can be broken into smaller, manageable services.
2. **High Scalability Needs**: Suitable for applications requiring independent scaling of components.
3. **Fault Tolerance and High Availability**: Perfect for systems where failure isolation and uptime are critical.
4. **Distributed Teams**: Enables teams to work independently on different services.
5. **Frequent Updates**: Supports continuous deployment and A/B testing for individual services.
6. **Technology Diversity**: Allows the use of different technologies for different services.
1. **Small to Medium Projects**: Ideal for applications with limited complexity and scope.
2. **Rapid Development**: Suitable for projects requiring quick development and deployment.
3. **Small Teams**: Works well for small teams with limited resources.
4. **Low Scalability Needs**: Best for applications with predictable and low traffic.
## Challenges
- Increased complexity in management, DevOps overhead, data consistency, latency, and higher costs.
- Harder to maintain as the codebase grows.
- Limited scalability (scaling requires scaling the entire application).
- Difficult to adopt new technologies incrementally.
## The Domain And Bounded Context - Service Boundary
## The Domain And Bounded Context
- `Identity Service`: The Identity Service is a bounded context for the authentication and authorization of users using [Identity Server](https://github.com/DuendeSoftware/IdentityServer). This service is responsible for creating new users and their corresponding roles and permissions using [.Net Core Identity](https://docs.microsoft.com/en-us/aspnet/core/security/authentication/identity) and Jwt authentication and authorization.
- `Identity`: The Identity is a bounded context for the authentication and authorization of users using [Identity Server](https://github.com/DuendeSoftware/IdentityServer). This service is responsible for creating new users and their corresponding roles and permissions using [.Net Core Identity](https://docs.microsoft.com/en-us/aspnet/core/security/authentication/identity) and Jwt authentication and authorization.
- `Flight Service`: The Flight Service is a bounded context `CRUD` service to handle flight related operations.
- `Flight`: The Flight is a bounded context `CRUD` service to handle flight related operations.
- `Passenger Service`: The Passenger Service is a bounded context for managing passenger information, tracking activities and subscribing to get notification for out of stock products.
- `Passenger`: The Passenger is a bounded context for managing passenger information, tracking activities and subscribing to get notification for out of stock products.
- `Booking Service`: The Booking Service is a bounded context for managing all operation related to booking ticket.
- `Booking`: The Booking is a bounded context for managing all operation related to booking ticket.
![](./assets/booking-microservices.png)
![](./assets/booking-monolith.png)
## Structure of Project
@ -178,7 +166,7 @@ dotnet tool restore
```
### Husky
Here we use `husky` to handel some pre commit rules and we used `conventional commits` rules and `formatting` as pre commit rules, here in [package.json](.././package.json). of course, we can add more rules for pre commit in future. (find more about husky in the [documentation](https://typicode.github.io/husky/get-started.html))
Here we use `husky` to handel some pre commit rules and we used `conventional commits` rules and `formatting` as pre commit rules, here in [package.json](./package.json). of course, we can add more rules for pre commit in future. (find more about husky in the [documentation](https://typicode.github.io/husky/get-started.html))
We need to install `husky` package for `manage` `pre commits hooks` and also I add two packages `@commitlint/cli` and `@commitlint/config-conventional` for handling conventional commits rules in [package.json](.././package.json).
Run the command bellow in the root of project to install all npm dependencies related to husky:
@ -205,24 +193,13 @@ Run the following commands to [Config SSL](https://docs.microsoft.com/en-us/aspn
dotnet dev-certs https -ep %USERPROFILE%\.aspnet\https\aspnetapp.pfx -p password
dotnet dev-certs https --trust
```
> Note: for running this command in `powershell` use `$env:USERPROFILE` instead of `%USERPROFILE%`*
***Note:** for running this command in `powershell` use `$env:USERPROFILE` instead of `%USERPROFILE%`*
#### macOS or Linux
```bash
dotnet dev-certs https -ep ${HOME}/.aspnet/https/aspnetapp.pfx -p $CREDENTIAL_PLACEHOLDER$
dotnet dev-certs https --trust
```
### Aspire
To run the application using the `ASPIRE App Host`, execute the following command from the solution root:
```bash
dotnet run --project ./src/Aspire/src/AppHost
```
> Note:The `ASPIRE dashboard` will be available at `http://localhost:18888`
> ### Docker Compose
@ -232,41 +209,28 @@ To run this app in `Docker`, use the [docker-compose.yaml](./deployments/docker-
docker-compose -f ./deployments/docker-compose/docker-compose.yaml up -d
```
> ### Kubernetes
To `configure TLS` in the `Kubernetes cluster`, we need to install `cert-manager` based on the [docs](https://cert-manager.io/docs/installation) and run the following commands to apply TLS in our application. Here, we use [Let's Encrypt](https://letsencrypt.org/) to encrypt our certificate.
```bash
kubectl apply -f ./deployments/kubernetes/booking-cert-manager.yml
```
To apply all necessary `deployments`, `pods`, `services`, `ingress`, and `config maps`, please run the following command:
```bash
kubectl apply -f ./deployments/kubernetes/booking-microservices.yml
```
> ### Build
To `build` all microservices, run this command in the `root` of the project:
To `build` monolith app, run this command in the `root` of the project:
```bash
dotnet build
```
> ### Run
To `run` each microservice, run this command in the root of the `Api` folder of each microservice where the `csproj` file is located:
To `run` monolith app, run this command in the root of the `Api` folder:
```bash
dotnet run
```
> ### Test
To `test` all microservices, run this command in the `root` of the project:
To `test` monolith app, run this command in the `root` of the project:
```bash
dotnet test
```
> ### Documentation Apis
Each microservice provides `API documentation` and navigate to `/swagger` for `Swagger OpenAPI` or `/scalar/v1` for `Scalar OpenAPI` to visit list of endpoints.
For checking `API documentation`, navigate to `/swagger` for `Swagger OpenAPI` or `/scalar/v1` for `Scalar OpenAPI` to visit list of endpoints.
As part of API testing, I created the [booking.rest](./booking.rest) file which can be run with the [REST Client](https://github.com/Huachao/vscode-restclient) `VSCode plugin`.
@ -280,7 +244,7 @@ Thanks a bunch for supporting me!
## Contribution
Thanks to all [contributors](https://github.com/meysamhadeli/booking-microservices/graphs/contributors), you're awesome and this wouldn't be possible without you! The goal is to build a categorized, community-driven collection of very well-known resources.
Thanks to all [contributors](https://github.com/meysamhadeli/booking-monolith/graphs/contributors), you're awesome and this wouldn't be possible without you! The goal is to build a categorized, community-driven collection of very well-known resources.
Please follow this [contribution guideline](./CONTRIBUTION.md) to submit a pull request or create the issue.
@ -293,4 +257,4 @@ Please follow this [contribution guideline](./CONTRIBUTION.md) to submit a pull
- [https://github.com/pdevito3/MessageBusTestingInMemHarness](https://github.com/pdevito3/MessageBusTestingInMemHarness)
## License
This project is made available under the MIT license. See [LICENSE](https://github.com/meysamhadeli/booking-microservices/blob/main/LICENSE) for details.
This project is made available under the MIT license. See [LICENSE](https://github.com/meysamhadeli/booking-monolith/blob/main/LICENSE) for details.

View File

@ -29,4 +29,4 @@ app.UseEndpoints(endpoints =>
app.MapGet("/", x => x.Response.WriteAsync(appOptions.Name));
app.Run();
app.Run();

View File

@ -213,4 +213,4 @@ var gateway = builder.AddProject<Projects.ApiGateway>("api-gateway")
.WithHttpEndpoint(port: 5001, name: "gateway-http")
.WithHttpsEndpoint(port: 5000, name: "gateway-https");
builder.Build().Run();
builder.Build().Run();

View File

@ -47,4 +47,4 @@ public class CachingBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest,
return response;
}
}
}

View File

@ -4,4 +4,4 @@ public interface ICacheRequest
{
string CacheKey { get; }
DateTime? AbsoluteExpirationRelativeToNow { get; }
}
}

View File

@ -4,4 +4,4 @@ namespace BuildingBlocks.Caching
{
string CacheKey { get; }
}
}
}

View File

@ -36,4 +36,4 @@ namespace BuildingBlocks.Caching
return response;
}
}
}
}

View File

@ -7,4 +7,4 @@ public static class IdentityConstant
public const string Admin = "admin";
public const string User = "user";
}
}
}

View File

@ -8,4 +8,4 @@ public record FlightDeleted(Guid Id) : IIntegrationEvent;
public record AircraftCreated(Guid Id) : IIntegrationEvent;
public record AirportCreated(Guid Id) : IIntegrationEvent;
public record SeatCreated(Guid Id) : IIntegrationEvent;
public record SeatReserved(Guid Id) : IIntegrationEvent;
public record SeatReserved(Guid Id) : IIntegrationEvent;

View File

@ -2,4 +2,4 @@ using BuildingBlocks.Core.Event;
namespace BuildingBlocks.Contracts.EventBus.Messages;
public record UserCreated(Guid Id, string Name, string PassportNumber) : IIntegrationEvent;
public record UserCreated(Guid Id, string Name, string PassportNumber) : IIntegrationEvent;

View File

@ -3,4 +3,4 @@ using BuildingBlocks.Core.Event;
namespace BuildingBlocks.Contracts.EventBus.Messages;
public record PassengerRegistrationCompleted(Guid Id) : IIntegrationEvent;
public record PassengerCreated(Guid Id) : IIntegrationEvent;
public record PassengerCreated(Guid Id) : IIntegrationEvent;

View File

@ -2,4 +2,4 @@ using BuildingBlocks.Core.Event;
namespace BuildingBlocks.Contracts.EventBus.Messages;
public record BookingCreated(Guid Id) : IIntegrationEvent;
public record BookingCreated(Guid Id) : IIntegrationEvent;

View File

@ -9,4 +9,4 @@ public interface ICommand : ICommand<Unit>
public interface ICommand<out T> : IRequest<T>
where T : notnull
{
}
}

View File

@ -11,4 +11,4 @@ public interface ICommandHandler<in TCommand, TResponse> : IRequestHandler<TComm
where TCommand : ICommand<TResponse>
where TResponse : notnull
{
}
}

View File

@ -5,4 +5,4 @@ namespace BuildingBlocks.Core.CQRS;
public interface IQuery<out T> : IRequest<T>
where T : notnull
{
}
}

View File

@ -6,4 +6,4 @@ public interface IQueryHandler<in TQuery, TResponse> : IRequestHandler<TQuery, T
where TQuery : IQuery<TResponse>
where TResponse : notnull
{
}
}

View File

@ -34,4 +34,4 @@ public class CompositeEventMapper : IEventMapper
return null;
}
}
}

View File

@ -6,4 +6,4 @@ public enum EventType
DomainEvent = 1,
IntegrationEvent = 2,
InternalCommand = 4
}
}

View File

@ -2,4 +2,4 @@ namespace BuildingBlocks.Core.Event;
public interface IDomainEvent : IEvent
{
}
}

View File

@ -9,4 +9,4 @@ public interface IEvent : INotification
Guid EventId => NewId.NextGuid();
public DateTime OccurredOn => DateTime.Now;
public string EventType => GetType().AssemblyQualifiedName;
}
}

View File

@ -2,4 +2,4 @@ namespace BuildingBlocks.Core.Event;
public interface IHaveIntegrationEvent
{
}
}

View File

@ -5,4 +5,4 @@ namespace BuildingBlocks.Core.Event;
[ExcludeFromTopology]
public interface IIntegrationEvent : IEvent
{
}
}

View File

@ -2,4 +2,4 @@ namespace BuildingBlocks.Core.Event;
public interface IInternalCommand : IEvent
{
}
}

View File

@ -2,4 +2,4 @@ using BuildingBlocks.Core.CQRS;
namespace BuildingBlocks.Core.Event;
public record InternalCommand : IInternalCommand, ICommand;
public record InternalCommand : IInternalCommand, ICommand;

View File

@ -23,4 +23,4 @@ public class MessageEnvelope<TMessage> : MessageEnvelope
}
public new TMessage? Message { get; }
}
}

View File

@ -152,4 +152,4 @@ public sealed class EventDispatcher(
return headers;
}
}
}

View File

@ -8,4 +8,4 @@ public interface IEventDispatcher
where T : IEvent;
public Task SendAsync<T>(T @event, Type type = null, CancellationToken cancellationToken = default)
where T : IEvent;
}
}

View File

@ -6,4 +6,4 @@ public interface IEventMapper
{
IIntegrationEvent? MapToIntegrationEvent(IDomainEvent @event);
IInternalCommand? MapToInternalCommand(IDomainEvent @event);
}
}

View File

@ -3,4 +3,4 @@ using BuildingBlocks.Core.Event;
namespace BuildingBlocks.Core;
public record IntegrationEventWrapper<TDomainEventType>(TDomainEventType DomainEvent) : IIntegrationEvent
where TDomainEventType : IDomainEvent;
where TDomainEventType : IDomainEvent;

View File

@ -20,4 +20,4 @@ public abstract record Aggregate<TId> : Entity<TId>, IAggregate<TId>
return dequeuedEvents;
}
}
}

View File

@ -9,4 +9,4 @@ public abstract record Entity<T> : IEntity<T>
public long? LastModifiedBy { get; set; }
public bool IsDeleted { get; set; }
public long Version { get; set; }
}
}

View File

@ -10,4 +10,4 @@ public interface IAggregate : IEntity
{
IReadOnlyList<IDomainEvent> DomainEvents { get; }
IEvent[] ClearDomainEvents();
}
}

View File

@ -12,4 +12,4 @@ public interface IEntity : IVersion
public DateTime? LastModified { get; set; }
public long? LastModifiedBy { get; set; }
public bool IsDeleted { get; set; }
}
}

View File

@ -4,4 +4,4 @@ namespace BuildingBlocks.Core.Model;
public interface IVersion
{
long Version { get; set; }
}
}

View File

@ -33,4 +33,4 @@ public static class Extensions
return PageList<TEntity>.Create(items.AsReadOnly(), pageRequest.PageNumber, pageRequest.PageSize, total);
}
}
}

View File

@ -13,4 +13,4 @@ public interface IPageList<T>
int TotalCount { get; init; }
int PageNumber { get; init; }
int PageSize { get; init; }
}
}

View File

@ -4,4 +4,4 @@ using MediatR;
public interface IPageQuery<out TResponse> : IPageRequest, IRequest<TResponse>
where TResponse : class
{ }
{ }

View File

@ -6,4 +6,4 @@ public interface IPageRequest
int PageSize { get; init; }
string? Filters { get; init; }
string? SortOrder { get; init; }
}
}

View File

@ -16,4 +16,4 @@ public record PageList<T>(IReadOnlyList<T> Items, int PageNumber, int PageSize,
{
return new PageList<T>(items, pageNumber, pageSize, totalItems);
}
}
}

View File

@ -178,4 +178,4 @@ public abstract class AppDbContextBase : DbContext, IDbContext
throw new System.Exception("try for find IAggregate", ex);
}
}
}
}

View File

@ -57,4 +57,4 @@ namespace BuildingBlocks.EFCore
return CreateNewInstance(options);
}
}
}
}

View File

@ -78,4 +78,4 @@ where TResponse : notnull
return response;
}
}
}
}

View File

@ -138,4 +138,4 @@ public static class Extensions
await seedersManager.ExecuteSeedAsync();
}
}
}

View File

@ -9,4 +9,4 @@ namespace BuildingBlocks.EFCore
{
Task SeedAllAsync();
}
}
}

View File

@ -15,4 +15,4 @@ public interface IDbContext
Task RollbackTransactionAsync(CancellationToken cancellationToken = default);
IExecutionStrategy CreateExecutionStrategy();
Task ExecuteTransactionalAsync(CancellationToken cancellationToken = default);
}
}

View File

@ -4,4 +4,4 @@ public interface ISeedManager
{
Task ExecuteSeedAsync();
Task ExecuteTestSeedAsync();
}
}

View File

@ -3,4 +3,4 @@ namespace BuildingBlocks.EFCore;
public class PostgresOptions
{
public string ConnectionString { get; set; }
}
}

View File

@ -39,4 +39,4 @@ public class SeedManager(
logger.LogInformation("Seed {SeederName} is completed.", testSeeder.GetType().Name);
}
}
}
}

View File

@ -25,4 +25,4 @@ public class BackgroundWorker : BackgroundService
await perform(stoppingToken);
logger.LogInformation("Background worker stopped");
}, stoppingToken);
}
}

View File

@ -90,4 +90,4 @@ public static class EventStoreDBConfigExtensions
.AsImplementedInterfaces()
.WithTransientLifetime());
}
}
}

View File

@ -24,5 +24,4 @@ namespace BuildingBlocks.EventStoreDB.Events
public virtual void When(object @event) { }
}
}
}

View File

@ -36,4 +36,4 @@ public static class AggregateStreamExtensions
return aggregate;
}
}
}

View File

@ -40,4 +40,4 @@ public class EventTypeMapper
return type;
});
}
}

View File

@ -12,4 +12,4 @@ namespace BuildingBlocks.EventStoreDB.Events
public interface IAggregateEventSourcing<T> : IAggregateEventSourcing, IEntity<T>
{
}
}
}

View File

@ -6,4 +6,4 @@ namespace BuildingBlocks.EventStoreDB.Events;
public interface IEventHandler<in TEvent> : INotificationHandler<TEvent>
where TEvent : IEvent
{
}
}

View File

@ -4,4 +4,4 @@ namespace BuildingBlocks.EventStoreDB.Events;
public interface IExternalEvent : IEvent
{
}
}

View File

@ -3,4 +3,4 @@ namespace BuildingBlocks.EventStoreDB.Events;
public interface IProjection
{
void When(object @event);
}
}

View File

@ -26,5 +26,4 @@ public class StreamEvent<T> : StreamEvent where T : notnull
public StreamEvent(T data, EventMetadata metadata) : base(data, metadata)
{
}
}
}

View File

@ -16,4 +16,4 @@ public static class StreamEventExtensions
var type = typeof(StreamEvent<>).MakeGenericType(eventData.GetType());
return (StreamEvent)Activator.CreateInstance(type, eventData, metaData)!;
}
}
}

View File

@ -25,4 +25,4 @@ public class StreamNameMapper
return $"{tenantPrefix}{streamType.Name}-{aggregateId}";
}
}
}

View File

@ -23,4 +23,4 @@ public static class Extensions
.AddEventStoreDB(configuration)
.AddProjections(assembliesToScan);
}
}
}

View File

@ -7,4 +7,4 @@ public interface IProjectionProcessor
{
Task ProcessEventAsync<T>(StreamEvent<T> streamEvent, CancellationToken cancellationToken = default)
where T : INotification;
}
}

View File

@ -9,4 +9,4 @@ public interface IProjectionPublisher
where T : INotification;
Task PublishAsync(StreamEvent streamEvent, CancellationToken cancellationToken = default);
}
}

View File

@ -36,4 +36,4 @@ public class ProjectionPublisher : IProjectionPublisher
return (Task)method
.Invoke(this, new object[] { streamEvent, cancellationToken })!;
}
}
}

View File

@ -71,4 +71,4 @@ public class EventStoreDBRepository<T> : IEventStoreDBRepository<T> where T : cl
return events
.Select(EventStoreDBSerializer.ToJsonEventData);
}
}
}

View File

@ -30,4 +30,4 @@ public static class RepositoryExtensions
return await repository.Update(entity, expectedVersion, cancellationToken);
}
}
}

View File

@ -36,4 +36,4 @@ public static class EventStoreDBSerializer
Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(@event)),
Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new { }))
);
}
}

View File

@ -78,4 +78,4 @@ public static class JsonObjectContractProvider
.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
.OrderByDescending(e => e.GetParameters().Length)
.FirstOrDefault();
}
}

View File

@ -12,4 +12,4 @@ public class NonDefaultConstructorContractResolver : DefaultContractResolver
base.CreateConstructorParameters
);
}
}
}

View File

@ -65,4 +65,4 @@ public static class SerializationExtensions
{
return new StringContent(obj.ToJson(), Encoding.UTF8, "application/json");
}
}
}

View File

@ -73,4 +73,4 @@ public class EventStoreDBSubscriptionCheckpointRepository : ISubscriptionCheckpo
}
private static string GetCheckpointStreamName(string subscriptionId) => $"checkpoint_{subscriptionId}";
}
}

View File

@ -188,4 +188,4 @@ public class EventStoreDBSubscriptionToAll
logger.LogInformation("Checkpoint event - ignoring");
return true;
}
}
}

View File

@ -5,4 +5,4 @@ public interface ISubscriptionCheckpointRepository
ValueTask<ulong?> Load(string subscriptionId, CancellationToken ct);
ValueTask Store(string subscriptionId, ulong position, CancellationToken ct);
}
}

View File

@ -17,4 +17,4 @@ public class InMemorySubscriptionCheckpointRepository : ISubscriptionCheckpointR
return ValueTask.CompletedTask;
}
}
}

View File

@ -10,4 +10,4 @@ public class AggregateNotFoundException : System.Exception
{
return new AggregateNotFoundException(typeof(T).Name, id);
}
}
}

View File

@ -11,4 +11,4 @@ public class AppException : CustomException
public AppException(string message, System.Exception innerException, HttpStatusCode statusCode = HttpStatusCode.BadRequest, int? code = null) : base(message, innerException, statusCode, code)
{
}
}
}

View File

@ -10,4 +10,4 @@ namespace BuildingBlocks.Exception
}
}
}
}

View File

@ -8,4 +8,4 @@ namespace BuildingBlocks.Exception
{
}
}
}
}

View File

@ -34,4 +34,4 @@ public class CustomException : System.Exception
public HttpStatusCode StatusCode { get; }
public int? Code { get; }
}
}

View File

@ -13,4 +13,4 @@ namespace SmartCharging.Infrastructure.Exceptions
{
}
}
}
}

View File

@ -20,4 +20,4 @@ public class GrpcExceptionInterceptor : Interceptor
throw new RpcException(new Status(StatusCode.Internal, exception.Message));
}
}
}
}

View File

@ -14,4 +14,4 @@ namespace BuildingBlocks.Exception
{
}
}
}
}

View File

@ -8,4 +8,4 @@ namespace BuildingBlocks.Exception
{
}
}
}
}

View File

@ -9,4 +9,4 @@ public class ProblemDetailsWithCode : ProblemDetails
{
[JsonPropertyName("code")]
public int? Code { get; set; }
}
}

View File

@ -8,4 +8,4 @@ namespace BuildingBlocks.Exception
{
}
}
}
}

View File

@ -87,4 +87,4 @@ public static class Extensions
return app;
}
}
}

View File

@ -3,4 +3,4 @@ namespace BuildingBlocks.HealthCheck;
public class HealthOptions
{
public bool Enabled { get; set; } = true;
}
}

View File

@ -21,4 +21,4 @@ public class AuthHeaderHandler : DelegatingHandler
return base.SendAsync(request, cancellationToken);
}
}
}

View File

@ -74,4 +74,4 @@ namespace BuildingBlocks.Jwt
return services;
}
}
}
}

View File

@ -37,4 +37,4 @@ public class LoggingBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest,
_logger.LogInformation("[{Prefix}] Handled {X-RequestData}", prefix, typeof(TRequest).Name);
return response;
}
}
}

View File

@ -16,4 +16,4 @@ public static class Extensions
return services;
}
}
}

View File

@ -35,4 +35,4 @@ public class ConsumeFilter<T> : IFilter<ConsumeContext<T>>
public void Probe(ProbeContext context)
{
}
}
}

View File

@ -117,4 +117,4 @@ public static class Extensions
.Ignore<
ValidationException>(); // don't retry if we have invalid data and message goes to _error queue masstransit
}
}
}

View File

@ -7,4 +7,4 @@ public class RabbitMqOptions
public string UserName { get; set; }
public string Password { get; set; }
public ushort? Port { get; set; }
}
}

View File

@ -4,4 +4,4 @@ public enum TransportType
{
RabbitMq,
InMemory
}
}

View File

@ -49,4 +49,4 @@ namespace BuildingBlocks.Mongo
return services;
}
}
}
}

View File

@ -10,4 +10,4 @@ public interface IMongoDbContext : IDisposable
Task CommitTransactionAsync(CancellationToken cancellationToken = default);
Task RollbackTransaction(CancellationToken cancellationToken = default);
void AddCommand(Func<Task> func);
}
}

View File

@ -5,4 +5,4 @@ namespace BuildingBlocks.Mongo;
public interface IMongoRepository<TEntity, in TId> : IRepository<TEntity, TId>
where TEntity : class, IAggregate<TId>
{
}
}

View File

@ -2,4 +2,4 @@ namespace BuildingBlocks.Mongo;
public interface IMongoUnitOfWork<out TContext> : IUnitOfWork<TContext> where TContext : class, IMongoDbContext
{
}
}

View File

@ -46,4 +46,4 @@ public interface IRepository<TEntity, in TId> :
public interface IRepository<TEntity> : IRepository<TEntity, long>
where TEntity : class, IAggregate<long>
{
}
}

Some files were not shown because too many files have changed in this diff Show More