From 9cc2d3d95f4c0dc54d9c4d0dd3abd632d143bbfa Mon Sep 17 00:00:00 2001 From: Meysam Hadeli <35596795+meysamhadeli@users.noreply.github.com> Date: Fri, 20 Jan 2023 20:00:35 +0330 Subject: [PATCH 1/3] Update .gitpod.yml --- .gitpod.yml | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/.gitpod.yml b/.gitpod.yml index 2a157b8..ffa1bde 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -6,20 +6,11 @@ # https://www.gitpod.io/docs/configure/workspaces/ports image: - file: gitpod/workspace-dotnet - -caches: - dotnet: - paths: - - /usr/local/bin/docker-compose + file: .gitpod.Dockerfile # https://www.gitpod.io/docs/configure/workspaces/tasks#execution-order # https://www.gitpod.io/docs/configure/projects/prebuilds tasks: - - name: Setup kubectl - command: bash $GITPOD_REPO_ROOT/scripts/setup_kubectl_gitpod.sh - - name: Setup Self-Signed Certificate - command: bash $GITPOD_REPO_ROOT/scripts/self_signed_certificate_gitpod.sh - name: Init Docker-Compose init: | docker-compose pull From 5f767ce7e9a4b97c53b41b0854a2de327065f071 Mon Sep 17 00:00:00 2001 From: Meysam Hadeli <35596795+meysamhadeli@users.noreply.github.com> Date: Fri, 20 Jan 2023 20:03:07 +0330 Subject: [PATCH 2/3] Create gitpod.Dockerfile --- gitpod.Dockerfile | 1 + 1 file changed, 1 insertion(+) create mode 100644 gitpod.Dockerfile diff --git a/gitpod.Dockerfile b/gitpod.Dockerfile new file mode 100644 index 0000000..9c1e96b --- /dev/null +++ b/gitpod.Dockerfile @@ -0,0 +1 @@ +FROM gitpod/workspace-dotnet:latest From 48f9f4b066b9527a6b325d7c4d957b7bf9b104e2 Mon Sep 17 00:00:00 2001 From: meysamhadeli Date: Sat, 21 Jan 2023 02:34:03 +0330 Subject: [PATCH 3/3] fix: Fix optimistic concurrency issue --- .gitpod.yml | 11 +---------- src/BuildingBlocks/BuildingBlocks.csproj | 1 + src/BuildingBlocks/Core/Model/Aggregate.cs | 2 +- src/BuildingBlocks/EFCore/AppDbContextBase.cs | 19 +++++++++++++++---- ....cs => 20230120222214_initial.Designer.cs} | 2 +- ...9_initial.cs => 20230120222214_initial.cs} | 0 .../src/Flight/Aircrafts/Models/Aircraft.cs | 1 - .../Configurations/AircraftConfiguration.cs | 5 +++++ .../Configurations/AirportConfiguration.cs | 5 +++++ .../Configurations/FlightConfiguration.cs | 4 ++++ .../Data/Configurations/SeatConfiguration.cs | 3 +++ .../Flight/src/Flight/Data/FlightDbContext.cs | 1 - ...ner.cs => 20230120222458_Init.Designer.cs} | 6 +++++- ...3183335_Init.cs => 20230120222458_Init.cs} | 0 .../FlightDbContextModelSnapshot.cs | 4 ++++ .../Configurations/PassengerConfiguration.cs | 4 +++- ....cs => 20230120222631_initial.Designer.cs} | 3 ++- ...7_initial.cs => 20230120222631_initial.cs} | 0 .../PassengerDbContextModelSnapshot.cs | 1 + 19 files changed, 51 insertions(+), 21 deletions(-) rename src/BuildingBlocks/PersistMessageProcessor/Data/Migrations/{20230113183839_initial.Designer.cs => 20230120222214_initial.Designer.cs} (98%) rename src/BuildingBlocks/PersistMessageProcessor/Data/Migrations/{20230113183839_initial.cs => 20230120222214_initial.cs} (100%) rename src/Services/Flight/src/Flight/Data/Migrations/{20230113183335_Init.Designer.cs => 20230120222458_Init.Designer.cs} (98%) rename src/Services/Flight/src/Flight/Data/Migrations/{20230113183335_Init.cs => 20230120222458_Init.cs} (100%) rename src/Services/Passenger/src/Passenger/Data/Migrations/{20230113183717_initial.Designer.cs => 20230120222631_initial.Designer.cs} (97%) rename src/Services/Passenger/src/Passenger/Data/Migrations/{20230113183717_initial.cs => 20230120222631_initial.cs} (100%) diff --git a/.gitpod.yml b/.gitpod.yml index 2a157b8..ffa1bde 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -6,20 +6,11 @@ # https://www.gitpod.io/docs/configure/workspaces/ports image: - file: gitpod/workspace-dotnet - -caches: - dotnet: - paths: - - /usr/local/bin/docker-compose + file: .gitpod.Dockerfile # https://www.gitpod.io/docs/configure/workspaces/tasks#execution-order # https://www.gitpod.io/docs/configure/projects/prebuilds tasks: - - name: Setup kubectl - command: bash $GITPOD_REPO_ROOT/scripts/setup_kubectl_gitpod.sh - - name: Setup Self-Signed Certificate - command: bash $GITPOD_REPO_ROOT/scripts/self_signed_certificate_gitpod.sh - name: Init Docker-Compose init: | docker-compose pull diff --git a/src/BuildingBlocks/BuildingBlocks.csproj b/src/BuildingBlocks/BuildingBlocks.csproj index 2da37be..3135285 100644 --- a/src/BuildingBlocks/BuildingBlocks.csproj +++ b/src/BuildingBlocks/BuildingBlocks.csproj @@ -35,6 +35,7 @@ + diff --git a/src/BuildingBlocks/Core/Model/Aggregate.cs b/src/BuildingBlocks/Core/Model/Aggregate.cs index 42c87ca..14697d5 100644 --- a/src/BuildingBlocks/Core/Model/Aggregate.cs +++ b/src/BuildingBlocks/Core/Model/Aggregate.cs @@ -25,7 +25,7 @@ namespace BuildingBlocks.Core.Model return dequeuedEvents; } - public long Version { get; set; } = -1; + public long Version { get; set; } public TId Id { get; set; } } diff --git a/src/BuildingBlocks/EFCore/AppDbContextBase.cs b/src/BuildingBlocks/EFCore/AppDbContextBase.cs index 88db419..57b4720 100644 --- a/src/BuildingBlocks/EFCore/AppDbContextBase.cs +++ b/src/BuildingBlocks/EFCore/AppDbContextBase.cs @@ -7,13 +7,16 @@ using Microsoft.EntityFrameworkCore.Storage; namespace BuildingBlocks.EFCore; +using System.Data; + public abstract class AppDbContextBase : DbContext, IDbContext { private readonly ICurrentUserProvider _currentUserProvider; private IDbContextTransaction _currentTransaction; - protected AppDbContextBase(DbContextOptions options, ICurrentUserProvider currentUserProvider = null) : base(options) + protected AppDbContextBase(DbContextOptions options, ICurrentUserProvider currentUserProvider = null) : + base(options) { _currentUserProvider = currentUserProvider; } @@ -30,7 +33,7 @@ public abstract class AppDbContextBase : DbContext, IDbContext return; } - _currentTransaction ??= await Database.BeginTransactionAsync(cancellationToken); + _currentTransaction ??= await Database.BeginTransactionAsync(IsolationLevel.ReadCommitted, cancellationToken); } public async Task CommitTransactionAsync(CancellationToken cancellationToken = default) @@ -68,7 +71,16 @@ public abstract class AppDbContextBase : DbContext, IDbContext public override Task SaveChangesAsync(CancellationToken cancellationToken = default) { OnBeforeSaving(); - return base.SaveChangesAsync(cancellationToken); + try + { + return base.SaveChangesAsync(cancellationToken); + } + catch (DbUpdateConcurrencyException ex) + { + var data = ex.Entries.Single(); + data.OriginalValues.SetValues(data.GetDatabaseValues() ?? throw new InvalidOperationException()); + return base.SaveChangesAsync(cancellationToken); + } } public IReadOnlyList GetDomainEvents() @@ -104,7 +116,6 @@ public abstract class AppDbContextBase : DbContext, IDbContext case EntityState.Added: entry.Entity.CreatedBy = userId; entry.Entity.CreatedAt = DateTime.Now; - entry.Entity.Version++; break; case EntityState.Modified: diff --git a/src/BuildingBlocks/PersistMessageProcessor/Data/Migrations/20230113183839_initial.Designer.cs b/src/BuildingBlocks/PersistMessageProcessor/Data/Migrations/20230120222214_initial.Designer.cs similarity index 98% rename from src/BuildingBlocks/PersistMessageProcessor/Data/Migrations/20230113183839_initial.Designer.cs rename to src/BuildingBlocks/PersistMessageProcessor/Data/Migrations/20230120222214_initial.Designer.cs index e6ae47d..3265c90 100644 --- a/src/BuildingBlocks/PersistMessageProcessor/Data/Migrations/20230113183839_initial.Designer.cs +++ b/src/BuildingBlocks/PersistMessageProcessor/Data/Migrations/20230120222214_initial.Designer.cs @@ -12,7 +12,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; namespace BuildingBlocks.PersistMessageProcessor.Data.Migrations { [DbContext(typeof(PersistMessageDbContext))] - [Migration("20230113183839_initial")] + [Migration("20230120222214_initial")] partial class initial { /// diff --git a/src/BuildingBlocks/PersistMessageProcessor/Data/Migrations/20230113183839_initial.cs b/src/BuildingBlocks/PersistMessageProcessor/Data/Migrations/20230120222214_initial.cs similarity index 100% rename from src/BuildingBlocks/PersistMessageProcessor/Data/Migrations/20230113183839_initial.cs rename to src/BuildingBlocks/PersistMessageProcessor/Data/Migrations/20230120222214_initial.cs diff --git a/src/Services/Flight/src/Flight/Aircrafts/Models/Aircraft.cs b/src/Services/Flight/src/Flight/Aircrafts/Models/Aircraft.cs index 6a67276..7c37fb5 100644 --- a/src/Services/Flight/src/Flight/Aircrafts/Models/Aircraft.cs +++ b/src/Services/Flight/src/Flight/Aircrafts/Models/Aircraft.cs @@ -1,5 +1,4 @@ using BuildingBlocks.Core.Model; -using BuildingBlocks.IdsGenerator; using Flight.Aircrafts.Features.CreateAircraft.Events.Domain.V1; namespace Flight.Aircrafts.Models; diff --git a/src/Services/Flight/src/Flight/Data/Configurations/AircraftConfiguration.cs b/src/Services/Flight/src/Flight/Data/Configurations/AircraftConfiguration.cs index 2af92aa..71fc974 100644 --- a/src/Services/Flight/src/Flight/Data/Configurations/AircraftConfiguration.cs +++ b/src/Services/Flight/src/Flight/Data/Configurations/AircraftConfiguration.cs @@ -8,8 +8,13 @@ public class AircraftConfiguration : IEntityTypeConfiguration { public void Configure(EntityTypeBuilder builder) { + builder.ToTable(nameof(Aircraft)); builder.HasKey(r => r.Id); builder.Property(r => r.Id).ValueGeneratedNever(); + + + // // ref: https://learn.microsoft.com/en-us/ef/core/saving/concurrency?tabs=fluent-api + builder.Property(r => r.Version).IsConcurrencyToken(); } } diff --git a/src/Services/Flight/src/Flight/Data/Configurations/AirportConfiguration.cs b/src/Services/Flight/src/Flight/Data/Configurations/AirportConfiguration.cs index 8fc776a..b3f475b 100644 --- a/src/Services/Flight/src/Flight/Data/Configurations/AirportConfiguration.cs +++ b/src/Services/Flight/src/Flight/Data/Configurations/AirportConfiguration.cs @@ -8,9 +8,14 @@ public class AirportConfiguration: IEntityTypeConfiguration { public void Configure(EntityTypeBuilder builder) { + builder.ToTable(nameof(Airport)); builder.HasKey(r => r.Id); builder.Property(r => r.Id).ValueGeneratedNever(); + + + // // ref: https://learn.microsoft.com/en-us/ef/core/saving/concurrency?tabs=fluent-api + builder.Property(r => r.Version).IsConcurrencyToken(); } } diff --git a/src/Services/Flight/src/Flight/Data/Configurations/FlightConfiguration.cs b/src/Services/Flight/src/Flight/Data/Configurations/FlightConfiguration.cs index 181dbab..42e549e 100644 --- a/src/Services/Flight/src/Flight/Data/Configurations/FlightConfiguration.cs +++ b/src/Services/Flight/src/Flight/Data/Configurations/FlightConfiguration.cs @@ -17,6 +17,10 @@ public class FlightConfiguration : IEntityTypeConfiguration r.Id); builder.Property(r => r.Id).ValueGeneratedNever(); + + // // ref: https://learn.microsoft.com/en-us/ef/core/saving/concurrency?tabs=fluent-api + builder.Property(r => r.Version).IsConcurrencyToken(); + builder .HasOne() .WithMany() diff --git a/src/Services/Flight/src/Flight/Data/Configurations/SeatConfiguration.cs b/src/Services/Flight/src/Flight/Data/Configurations/SeatConfiguration.cs index 0ff9083..e1e6e0f 100644 --- a/src/Services/Flight/src/Flight/Data/Configurations/SeatConfiguration.cs +++ b/src/Services/Flight/src/Flight/Data/Configurations/SeatConfiguration.cs @@ -16,6 +16,9 @@ public class SeatConfiguration : IEntityTypeConfiguration builder.HasKey(r => r.Id); builder.Property(r => r.Id).ValueGeneratedNever(); + // // ref: https://learn.microsoft.com/en-us/ef/core/saving/concurrency?tabs=fluent-api + builder.Property(r => r.Version).IsConcurrencyToken(); + builder .HasOne() .WithMany() diff --git a/src/Services/Flight/src/Flight/Data/FlightDbContext.cs b/src/Services/Flight/src/Flight/Data/FlightDbContext.cs index 8274430..60e6e13 100644 --- a/src/Services/Flight/src/Flight/Data/FlightDbContext.cs +++ b/src/Services/Flight/src/Flight/Data/FlightDbContext.cs @@ -7,7 +7,6 @@ using Microsoft.EntityFrameworkCore; namespace Flight.Data; - public sealed class FlightDbContext : AppDbContextBase { public FlightDbContext(DbContextOptions options, ICurrentUserProvider currentUserProvider) : base( diff --git a/src/Services/Flight/src/Flight/Data/Migrations/20230113183335_Init.Designer.cs b/src/Services/Flight/src/Flight/Data/Migrations/20230120222458_Init.Designer.cs similarity index 98% rename from src/Services/Flight/src/Flight/Data/Migrations/20230113183335_Init.Designer.cs rename to src/Services/Flight/src/Flight/Data/Migrations/20230120222458_Init.Designer.cs index 9374273..b83b9b0 100644 --- a/src/Services/Flight/src/Flight/Data/Migrations/20230113183335_Init.Designer.cs +++ b/src/Services/Flight/src/Flight/Data/Migrations/20230120222458_Init.Designer.cs @@ -12,7 +12,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; namespace Flight.Data.Migrations { [DbContext(typeof(FlightDbContext))] - [Migration("20230113183335_Init")] + [Migration("20230120222458_Init")] partial class Init { /// @@ -64,6 +64,7 @@ namespace Flight.Data.Migrations .HasColumnName("name"); b.Property("Version") + .IsConcurrencyToken() .HasColumnType("bigint") .HasColumnName("version"); @@ -112,6 +113,7 @@ namespace Flight.Data.Migrations .HasColumnName("name"); b.Property("Version") + .IsConcurrencyToken() .HasColumnType("bigint") .HasColumnName("version"); @@ -191,6 +193,7 @@ namespace Flight.Data.Migrations .HasColumnName("status"); b.Property("Version") + .IsConcurrencyToken() .HasColumnType("bigint") .HasColumnName("version"); @@ -255,6 +258,7 @@ namespace Flight.Data.Migrations .HasColumnName("type"); b.Property("Version") + .IsConcurrencyToken() .HasColumnType("bigint") .HasColumnName("version"); diff --git a/src/Services/Flight/src/Flight/Data/Migrations/20230113183335_Init.cs b/src/Services/Flight/src/Flight/Data/Migrations/20230120222458_Init.cs similarity index 100% rename from src/Services/Flight/src/Flight/Data/Migrations/20230113183335_Init.cs rename to src/Services/Flight/src/Flight/Data/Migrations/20230120222458_Init.cs diff --git a/src/Services/Flight/src/Flight/Data/Migrations/FlightDbContextModelSnapshot.cs b/src/Services/Flight/src/Flight/Data/Migrations/FlightDbContextModelSnapshot.cs index 3a944c1..8a46c93 100644 --- a/src/Services/Flight/src/Flight/Data/Migrations/FlightDbContextModelSnapshot.cs +++ b/src/Services/Flight/src/Flight/Data/Migrations/FlightDbContextModelSnapshot.cs @@ -61,6 +61,7 @@ namespace Flight.Data.Migrations .HasColumnName("name"); b.Property("Version") + .IsConcurrencyToken() .HasColumnType("bigint") .HasColumnName("version"); @@ -109,6 +110,7 @@ namespace Flight.Data.Migrations .HasColumnName("name"); b.Property("Version") + .IsConcurrencyToken() .HasColumnType("bigint") .HasColumnName("version"); @@ -188,6 +190,7 @@ namespace Flight.Data.Migrations .HasColumnName("status"); b.Property("Version") + .IsConcurrencyToken() .HasColumnType("bigint") .HasColumnName("version"); @@ -252,6 +255,7 @@ namespace Flight.Data.Migrations .HasColumnName("type"); b.Property("Version") + .IsConcurrencyToken() .HasColumnType("bigint") .HasColumnName("version"); diff --git a/src/Services/Passenger/src/Passenger/Data/Configurations/PassengerConfiguration.cs b/src/Services/Passenger/src/Passenger/Data/Configurations/PassengerConfiguration.cs index eb787bd..9bfeff0 100644 --- a/src/Services/Passenger/src/Passenger/Data/Configurations/PassengerConfiguration.cs +++ b/src/Services/Passenger/src/Passenger/Data/Configurations/PassengerConfiguration.cs @@ -1,4 +1,3 @@ -using BuildingBlocks.EFCore; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; @@ -12,5 +11,8 @@ public class PassengerConfiguration: IEntityTypeConfiguration r.Id); builder.Property(r => r.Id).ValueGeneratedNever(); + + // // ref: https://learn.microsoft.com/en-us/ef/core/saving/concurrency?tabs=fluent-api + builder.Property(r => r.Version).IsConcurrencyToken(); } } diff --git a/src/Services/Passenger/src/Passenger/Data/Migrations/20230113183717_initial.Designer.cs b/src/Services/Passenger/src/Passenger/Data/Migrations/20230120222631_initial.Designer.cs similarity index 97% rename from src/Services/Passenger/src/Passenger/Data/Migrations/20230113183717_initial.Designer.cs rename to src/Services/Passenger/src/Passenger/Data/Migrations/20230120222631_initial.Designer.cs index ee01a84..4a9eca5 100644 --- a/src/Services/Passenger/src/Passenger/Data/Migrations/20230113183717_initial.Designer.cs +++ b/src/Services/Passenger/src/Passenger/Data/Migrations/20230120222631_initial.Designer.cs @@ -12,7 +12,7 @@ using Passenger.Data; namespace Passenger.Data.Migrations { [DbContext(typeof(PassengerDbContext))] - [Migration("20230113183717_initial")] + [Migration("20230120222631_initial")] partial class initial { /// @@ -68,6 +68,7 @@ namespace Passenger.Data.Migrations .HasColumnName("passport_number"); b.Property("Version") + .IsConcurrencyToken() .HasColumnType("bigint") .HasColumnName("version"); diff --git a/src/Services/Passenger/src/Passenger/Data/Migrations/20230113183717_initial.cs b/src/Services/Passenger/src/Passenger/Data/Migrations/20230120222631_initial.cs similarity index 100% rename from src/Services/Passenger/src/Passenger/Data/Migrations/20230113183717_initial.cs rename to src/Services/Passenger/src/Passenger/Data/Migrations/20230120222631_initial.cs diff --git a/src/Services/Passenger/src/Passenger/Data/Migrations/PassengerDbContextModelSnapshot.cs b/src/Services/Passenger/src/Passenger/Data/Migrations/PassengerDbContextModelSnapshot.cs index 20ec96f..6612a81 100644 --- a/src/Services/Passenger/src/Passenger/Data/Migrations/PassengerDbContextModelSnapshot.cs +++ b/src/Services/Passenger/src/Passenger/Data/Migrations/PassengerDbContextModelSnapshot.cs @@ -65,6 +65,7 @@ namespace Passenger.Data.Migrations .HasColumnName("passport_number"); b.Property("Version") + .IsConcurrencyToken() .HasColumnType("bigint") .HasColumnName("version");