Merge pull request #239 from meysamhadeli/refactor/refactor-id-genrator

Refactor/refactor id genrator
This commit is contained in:
Meysam Hadeli 2023-03-30 12:20:09 +03:30 committed by GitHub
commit 021e218671
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
45 changed files with 67 additions and 70 deletions

View File

@ -163,8 +163,7 @@ docker-compose -f ./deployments/docker-compose/docker-compose.yaml up -d
```
> ### Kubernetes
For Configure TLS in kubernetes cluster we need install `cert-manager` base on [docs](https://cert-manager.io/docs/installation) and run the following commands for apply TLS in our application
Here we use [LetsEncrypt](https://letsencrypt.org/) for encrypt our certificate.
For Configure TLS in kubernetes cluster we need install `cert-manager` base on [docs](https://cert-manager.io/docs/installation) and run the following commands for apply TLS in our application. Here we use [LetsEncrypt](https://letsencrypt.org/) for encryption our certificate.
```bash
kubectl apply -f ./deployments/kubernetes/booking-cert-manager.yml

View File

@ -18,6 +18,7 @@
<PackageReference Include="AspNetCore.HealthChecks.Rabbitmq" Version="6.0.2" />
<PackageReference Include="AspNetCore.HealthChecks.UI.SQLite.Storage" Version="6.0.5" />
<PackageReference Include="Ben.BlockingDetector" Version="0.0.4" />
<PackageReference Include="DotNetEnv" Version="2.5.0" />
<PackageReference Include="EasyCaching.Core" Version="1.8.0" />
<PackageReference Include="EasyCaching.InMemory" Version="1.8.0" />
<PackageReference Include="EasyNetQ.Management.Client" Version="1.4.2" />

View File

@ -5,7 +5,7 @@ namespace BuildingBlocks.Core.Event;
public interface IEvent : INotification
{
long EventId => SnowFlakIdGenerator.NewId();
long EventId => SnowflakeIdGenerator.NewId();
public DateTime OccurredOn => DateTime.Now;
public string EventType => GetType().AssemblyQualifiedName;
}

View File

@ -1,4 +1,3 @@
using Ardalis.GuardClauses;
using IdGen;
namespace BuildingBlocks.IdsGenerator;
@ -6,16 +5,16 @@ namespace BuildingBlocks.IdsGenerator;
// Ref: https://github.com/RobThree/IdGen
// https://github.com/RobThree/IdGen/issues/34
// https://www.callicoder.com/distributed-unique-id-sequence-number-generator/
public static class SnowFlakIdGenerator
public static class SnowflakeIdGenerator
{
private static IdGenerator _generator;
public static void Configure(int generatorId)
private static readonly IdGenerator Generator;
static SnowflakeIdGenerator()
{
Guard.Against.NegativeOrZero(generatorId, nameof(generatorId));
// Read `GENERATOR_ID` from .env file in service root folder or system environment variables
var generatorId = DotNetEnv.Env.GetInt("GENERATOR_ID", 0);
// Let's say we take jan 17st 2022 as our epoch
var epoch = new DateTime(2022, 1, 1, 0, 0, 0, DateTimeKind.Local);
// Let's say we take current time as our epoch
var epoch = DateTime.Now;
// Create an ID with 45 bits for timestamp, 2 for generator-id
// and 16 for sequence
@ -26,8 +25,11 @@ public static class SnowFlakIdGenerator
// Create an IdGenerator with it's generator-id set to 0, our custom epoch
// and id-structure
_generator = new IdGenerator(0, options);
Generator = new IdGenerator(generatorId, options);
}
public static long NewId() => _generator.CreateId();
public static long NewId()
{
return Generator.CreateId();
}
}

View File

@ -202,7 +202,7 @@ public class PersistMessageProcessor : IPersistMessageProcessor
if (messageEnvelope.Message is IEvent message)
id = message.EventId;
else
id = SnowFlakIdGenerator.NewId();
id = SnowflakeIdGenerator.NewId();
await _persistMessageDbContext.PersistMessages.AddAsync(
new PersistMessage(

View File

@ -0,0 +1 @@
GENERATOR_ID=4

View File

@ -15,7 +15,7 @@ using Passenger;
public record CreateBooking(long PassengerId, long FlightId, string Description) : ICommand<CreateBookingResult>, IInternalCommand
{
public long Id { get; init; } = SnowFlakIdGenerator.NewId();
public long Id { get; init; } = SnowflakeIdGenerator.NewId();
}
public record CreateBookingResult(ulong Id);

View File

@ -41,7 +41,7 @@ public class BookingProjection : IProjectionProcessor
{
var bookingReadModel = new BookingReadModel
{
Id = SnowFlakIdGenerator.NewId(),
Id = SnowflakeIdGenerator.NewId(),
Trip = @event.Trip,
BookId = @event.Id,
PassengerInfo = @event.PassengerInfo,

View File

@ -35,6 +35,9 @@ public static class InfrastructureExtensions
var configuration = builder.Configuration;
var env = builder.Environment;
// https://github.com/tonerdo/dotnet-env
DotNetEnv.Env.TraversePath().Load();
builder.Services.AddScoped<ICurrentUserProvider, CurrentUserProvider>();
builder.Services.AddScoped<IEventMapper, EventMapper>();
builder.Services.AddScoped<IEventDispatcher, EventDispatcher>();
@ -76,8 +79,6 @@ public static class InfrastructureExtensions
builder.Services.AddCustomOpenTelemetry();
builder.Services.AddTransient<AuthHeaderHandler>();
SnowFlakIdGenerator.Configure(3);
// ref: https://github.com/oskardudycz/EventSourcing.NetCore/tree/main/Sample/EventStoreDB/ECommerce
builder.Services.AddEventStore(configuration, typeof(BookingRoot).Assembly)
.AddEventStoreDBSubscriptionToAll();

View File

@ -9,7 +9,7 @@ public sealed class FakeCreateBookingCommand : AutoFaker<CreateBooking>
{
public FakeCreateBookingCommand()
{
RuleFor(r => r.Id, _ => SnowFlakIdGenerator.NewId());
RuleFor(r => r.Id, _ => SnowflakeIdGenerator.NewId());
RuleFor(r => r.FlightId, _ => 1);
RuleFor(r => r.PassengerId, _ => 1);
}

View File

@ -8,6 +8,6 @@ public class FakePassengerResponse : AutoFaker<PassengerResponse>
{
public FakePassengerResponse()
{
RuleFor(r => r.Id, _ => SnowFlakIdGenerator.NewId());
RuleFor(r => r.Id, _ => SnowflakeIdGenerator.NewId());
}
}

View File

@ -0,0 +1 @@
GENERATOR_ID=1

View File

@ -7,7 +7,7 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Flight\Flight.csproj"/>
<ProjectReference Include="..\Flight\Flight.csproj" />
</ItemGroup>
<ItemGroup>

View File

@ -11,11 +11,11 @@ public class AircraftMappings : IRegister
public void Register(TypeAdapterConfig config)
{
config.NewConfig<CreateAircraftMongo, AircraftReadModel>()
.Map(d => d.Id, s => SnowFlakIdGenerator.NewId())
.Map(d => d.Id, s => SnowflakeIdGenerator.NewId())
.Map(d => d.AircraftId, s => s.Id);
config.NewConfig<Aircraft, AircraftReadModel>()
.Map(d => d.Id, s => SnowFlakIdGenerator.NewId())
.Map(d => d.Id, s => SnowflakeIdGenerator.NewId())
.Map(d => d.AircraftId, s => s.Id);
config.NewConfig<CreateAircraftRequestDto, CreatingAircraft.V1.CreateAircraft>()

View File

@ -17,7 +17,7 @@ using Microsoft.EntityFrameworkCore;
public record CreateAircraft(string Name, string Model, int ManufacturingYear) : ICommand<CreateAircraftResult>, IInternalCommand
{
public long Id { get; init; } = SnowFlakIdGenerator.NewId();
public long Id { get; init; } = SnowflakeIdGenerator.NewId();
}
public record CreateAircraftResult(long Id);

View File

@ -10,11 +10,11 @@ public class AirportMappings : IRegister
public void Register(TypeAdapterConfig config)
{
config.NewConfig<CreateAirportMongo, AirportReadModel>()
.Map(d => d.Id, s => SnowFlakIdGenerator.NewId())
.Map(d => d.Id, s => SnowflakeIdGenerator.NewId())
.Map(d => d.AirportId, s => s.Id);
config.NewConfig<Airport, AirportReadModel>()
.Map(d => d.Id, s => SnowFlakIdGenerator.NewId())
.Map(d => d.Id, s => SnowflakeIdGenerator.NewId())
.Map(d => d.AirportId, s => s.Id);
config.NewConfig<CreateAirportRequestDto, CreateAirport>()

View File

@ -16,7 +16,7 @@ using Microsoft.EntityFrameworkCore;
public record CreateAirport(string Name, string Address, string Code) : ICommand<CreateAirportResult>, IInternalCommand
{
public long Id { get; init; } = SnowFlakIdGenerator.NewId();
public long Id { get; init; } = SnowflakeIdGenerator.NewId();
}
public record CreateAirportResult(long Id);

View File

@ -31,7 +31,6 @@ using Serilog;
namespace Flight.Extensions.Infrastructure;
using BuildingBlocks.PersistMessageProcessor.Data;
using Microsoft.AspNetCore.HttpOverrides;
public static class InfrastructureExtensions
{
@ -40,6 +39,9 @@ public static class InfrastructureExtensions
var configuration = builder.Configuration;
var env = builder.Environment;
// https://github.com/tonerdo/dotnet-env
DotNetEnv.Env.TraversePath().Load();
builder.Services.AddScoped<ICurrentUserProvider, CurrentUserProvider>();
builder.Services.AddScoped<IEventMapper, EventMapper>();
builder.Services.AddScoped<IEventDispatcher, EventDispatcher>();
@ -86,8 +88,6 @@ public static class InfrastructureExtensions
options.Interceptors.Add<GrpcExceptionInterceptor>();
});
SnowFlakIdGenerator.Configure(1);
builder.Services.AddEasyCaching(options => { options.UseInMemory(configuration, "mem"); });
return builder;

View File

@ -19,7 +19,7 @@ public record CreateFlight(string FlightNumber, long AircraftId, long DepartureA
decimal DurationMinutes, DateTime FlightDate, Enums.FlightStatus Status,
decimal Price) : ICommand<CreateFlightResult>, IInternalCommand
{
public long Id { get; init; } = SnowFlakIdGenerator.NewId();
public long Id { get; init; } = SnowflakeIdGenerator.NewId();
}
public record CreateFlightResult(long Id);

View File

@ -19,11 +19,11 @@ public class FlightMappings : IRegister
x.ArriveDate, x.ArriveAirportId, x.DurationMinutes, x.FlightDate, x.Status, x.Price));
config.NewConfig<CreateFlightMongo, FlightReadModel>()
.Map(d => d.Id, s => SnowFlakIdGenerator.NewId())
.Map(d => d.Id, s => SnowflakeIdGenerator.NewId())
.Map(d => d.FlightId, s => s.Id);
config.NewConfig<Models.Flight, FlightReadModel>()
.Map(d => d.Id, s => SnowFlakIdGenerator.NewId())
.Map(d => d.Id, s => SnowflakeIdGenerator.NewId())
.Map(d => d.FlightId, s => s.Id);
config.NewConfig<FlightReadModel, FlightDto>()

View File

@ -17,7 +17,7 @@ using Microsoft.EntityFrameworkCore;
public record CreateSeat(string SeatNumber, Enums.SeatType Type, Enums.SeatClass Class, long FlightId) : ICommand<CreateSeatResult>, IInternalCommand
{
public long Id { get; init; } = SnowFlakIdGenerator.NewId();
public long Id { get; init; } = SnowflakeIdGenerator.NewId();
}
public record CreateSeatResult(long Id);

View File

@ -16,11 +16,11 @@ public class SeatMappings : IRegister
.ConstructUsing(x => new SeatDto(x.Id, x.SeatNumber, x.Type, x.Class, x.FlightId));
config.NewConfig<CreateSeatMongo, SeatReadModel>()
.Map(d => d.Id, s => SnowFlakIdGenerator.NewId())
.Map(d => d.Id, s => SnowflakeIdGenerator.NewId())
.Map(d => d.SeatId, s => s.Id);
config.NewConfig<Seat, SeatReadModel>()
.Map(d => d.Id, s => SnowFlakIdGenerator.NewId())
.Map(d => d.Id, s => SnowflakeIdGenerator.NewId())
.Map(d => d.SeatId, s => s.Id);
config.NewConfig<ReserveSeatMongo, SeatReadModel>()

View File

@ -10,7 +10,7 @@ public sealed class FakeCreateFlightCommand : AutoFaker<CreateFlight>
{
public FakeCreateFlightCommand()
{
RuleFor(r => r.Id, _ => SnowFlakIdGenerator.NewId());
RuleFor(r => r.Id, _ => SnowflakeIdGenerator.NewId());
RuleFor(r => r.FlightNumber, r => "12FF");
RuleFor(r => r.DepartureAirportId, _ => 1);
RuleFor(r => r.ArriveAirportId, _ => 2);

View File

@ -9,6 +9,6 @@ public class FakeCreateAircraftCommand : AutoFaker<CreateAircraft>
{
public FakeCreateAircraftCommand()
{
RuleFor(r => r.Id, _ => SnowFlakIdGenerator.NewId());
RuleFor(r => r.Id, _ => SnowflakeIdGenerator.NewId());
}
}

View File

@ -9,6 +9,6 @@ public class FakeCreateAirportCommand : AutoFaker<CreateAirport>
{
public FakeCreateAirportCommand()
{
RuleFor(r => r.Id, _ => SnowFlakIdGenerator.NewId());
RuleFor(r => r.Id, _ => SnowflakeIdGenerator.NewId());
}
}

View File

@ -10,7 +10,7 @@ public sealed class FakeCreateFlightCommand : AutoFaker<CreateFlight>
{
public FakeCreateFlightCommand()
{
RuleFor(r => r.Id, _ => SnowFlakIdGenerator.NewId());
RuleFor(r => r.Id, _ => SnowflakeIdGenerator.NewId());
RuleFor(r => r.FlightNumber, r => r.Random.Number(1000, 2000).ToString());
RuleFor(r => r.DepartureAirportId, _ => 1);
RuleFor(r => r.ArriveAirportId, _ => 2);

View File

@ -10,7 +10,7 @@ public class FakeCreateSeatCommand : AutoFaker<CreateSeat>
{
public FakeCreateSeatCommand(long flightId)
{
RuleFor(r => r.Id, _ => SnowFlakIdGenerator.NewId());
RuleFor(r => r.Id, _ => SnowflakeIdGenerator.NewId());
RuleFor(r => r.FlightId, _ => flightId);
RuleFor(r => r.Class, _ => SeatClass.Economy);
RuleFor(r => r.Type, _ => SeatType.Middle);

View File

@ -1,11 +0,0 @@
using BuildingBlocks.IdsGenerator;
namespace Unit.Test.Common;
public static class SnowFlakIdGeneratorFactory
{
public static void Create()
{
SnowFlakIdGenerator.Configure(1);
}
}

View File

@ -13,7 +13,6 @@ namespace Unit.Test.Common
{
public UnitTestFixture()
{
SnowFlakIdGeneratorFactory.Create();
Mapper = MapperFactory.Create();
DbContext = DbContextFactory.Create();
}

View File

@ -9,6 +9,6 @@ public class FakeCreateAircraftCommand : AutoFaker<CreateAircraft>
{
public FakeCreateAircraftCommand()
{
RuleFor(r => r.Id, _ => SnowFlakIdGenerator.NewId());
RuleFor(r => r.Id, _ => SnowflakeIdGenerator.NewId());
}
}

View File

@ -9,6 +9,6 @@ public class FakeCreateAirportCommand : AutoFaker<CreateAirport>
{
public FakeCreateAirportCommand()
{
RuleFor(r => r.Id, _ => SnowFlakIdGenerator.NewId());
RuleFor(r => r.Id, _ => SnowflakeIdGenerator.NewId());
}
}

View File

@ -9,7 +9,7 @@ public sealed class FakeCreateFlightCommand : AutoFaker<CreateFlight>
{
public FakeCreateFlightCommand()
{
RuleFor(r => r.Id, _ => SnowFlakIdGenerator.NewId());
RuleFor(r => r.Id, _ => SnowflakeIdGenerator.NewId());
RuleFor(r => r.FlightNumber, r => r.Random.Number(1000, 2000).ToString());
RuleFor(r => r.DepartureAirportId, _ => 1);
RuleFor(r => r.ArriveAirportId, _ => 2);

View File

@ -10,7 +10,7 @@ public class FakeCreateSeatCommand : AutoFaker<CreateSeat>
{
public FakeCreateSeatCommand()
{
RuleFor(r => r.Id, _ => SnowFlakIdGenerator.NewId());
RuleFor(r => r.Id, _ => SnowflakeIdGenerator.NewId());
RuleFor(r => r.FlightId, _ => 1);
RuleFor(r => r.SeatNumber, _ => "F99");
RuleFor(r => r.Type, _ => SeatType.Window);

View File

@ -0,0 +1 @@
GENERATOR_ID=2

View File

@ -37,6 +37,9 @@ public static class InfrastructureExtensions
var configuration = builder.Configuration;
var env = builder.Environment;
// https://github.com/tonerdo/dotnet-env
DotNetEnv.Env.TraversePath().Load();
builder.Services.AddScoped<ICurrentUserProvider, CurrentUserProvider>();
builder.Services.AddScoped<IEventMapper, EventMapper>();
builder.Services.AddScoped<IEventDispatcher, EventDispatcher>();
@ -76,8 +79,6 @@ public static class InfrastructureExtensions
builder.Services.AddCustomMassTransit(env, typeof(IdentityRoot).Assembly);
builder.Services.AddCustomOpenTelemetry();
SnowFlakIdGenerator.Configure(4);
builder.AddCustomIdentityServer();
builder.Services.Configure<ForwardedHeadersOptions>(options =>

View File

@ -0,0 +1 @@
GENERATOR_ID=3

View File

@ -6,7 +6,7 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Passenger\Passenger.csproj"/>
<ProjectReference Include="..\Passenger\Passenger.csproj" />
</ItemGroup>
</Project>

View File

@ -37,6 +37,9 @@ public static class InfrastructureExtensions
var configuration = builder.Configuration;
var env = builder.Environment;
// https://github.com/tonerdo/dotnet-env
DotNetEnv.Env.TraversePath().Load();
builder.Services.AddScoped<ICurrentUserProvider, CurrentUserProvider>();
builder.Services.AddScoped<IEventMapper, EventMapper>();
builder.Services.AddScoped<IEventDispatcher, EventDispatcher>();
@ -81,8 +84,6 @@ public static class InfrastructureExtensions
options.Interceptors.Add<GrpcExceptionInterceptor>();
});
SnowFlakIdGenerator.Configure(2);
return builder;
}

View File

@ -45,7 +45,7 @@ public class RegisterNewUserHandler : IConsumer<UserCreated>
return;
}
var passenger = Passengers.Models.Passenger.Create(SnowFlakIdGenerator.NewId(), context.Message.Name,
var passenger = Passengers.Models.Passenger.Create(SnowflakeIdGenerator.NewId(), context.Message.Name,
context.Message.PassportNumber);
await _passengerDbContext.AddAsync(passenger);

View File

@ -13,7 +13,7 @@ using Dtos;
public record CompleteRegisterPassenger(string PassportNumber, Enums.PassengerType PassengerType, int Age) : ICommand<CompleteRegisterPassengerResult>, IInternalCommand
{
public long Id { get; init; } = SnowFlakIdGenerator.NewId();
public long Id { get; init; } = SnowflakeIdGenerator.NewId();
}
public record CompleteRegisterPassengerResult(PassengerDto PassengerDto);

View File

@ -11,7 +11,7 @@ public class PassengerMappings : IRegister
public void Register(TypeAdapterConfig config)
{
config.NewConfig<CompleteRegisterPassengerMongoCommand, PassengerReadModel>()
.Map(d => d.Id, s => SnowFlakIdGenerator.NewId())
.Map(d => d.Id, s => SnowflakeIdGenerator.NewId())
.Map(d => d.PassengerId, s => s.Id);
config.NewConfig<CompleteRegisterPassengerRequestDto, CompleteRegisterPassenger>()

View File

@ -10,7 +10,7 @@ public sealed class FakeCompleteRegisterPassengerCommand : AutoFaker<CompleteReg
{
public FakeCompleteRegisterPassengerCommand(string passportNumber)
{
RuleFor(r => r.Id, _ => SnowFlakIdGenerator.NewId());
RuleFor(r => r.Id, _ => SnowflakeIdGenerator.NewId());
RuleFor(r => r.PassportNumber, _ => passportNumber);
RuleFor(r => r.PassengerType, _ => PassengerType.Male);
RuleFor(r => r.Age, _ => 30);

View File

@ -7,6 +7,6 @@ public static class FakePassengerCreated
{
public static global::Passenger.Passengers.Models.Passenger Generate(UserCreated userCreated)
{
return global::Passenger.Passengers.Models.Passenger.Create(SnowFlakIdGenerator.NewId(), userCreated.Name, userCreated.PassportNumber);
return global::Passenger.Passengers.Models.Passenger.Create(SnowflakeIdGenerator.NewId(), userCreated.Name, userCreated.PassportNumber);
}
}

View File

@ -8,6 +8,6 @@ public class FakePassengerResponse : AutoFaker<PassengerResponse>
{
public FakePassengerResponse()
{
RuleFor(r => r.Id, _ => SnowFlakIdGenerator.NewId());
RuleFor(r => r.Id, _ => SnowflakeIdGenerator.NewId());
}
}
}

View File

@ -8,7 +8,7 @@ public class FakeUserCreated : AutoFaker<UserCreated>
{
public FakeUserCreated()
{
RuleFor(r => r.Id, _ => SnowFlakIdGenerator.NewId());
RuleFor(r => r.Id, _ => SnowflakeIdGenerator.NewId());
RuleFor(r => r.Name, _ => "Sam");
RuleFor(r => r.PassportNumber, _ => "123456789");
}