mirror of
https://github.com/meysamhadeli/booking-microservices.git
synced 2026-04-24 22:38:09 +08:00
add optimistic concurrency
This commit is contained in:
parent
ed931ae0f2
commit
3d3f46f0b1
@ -25,9 +25,7 @@ namespace BuildingBlocks.Domain.Model
|
||||
return dequeuedEvents;
|
||||
}
|
||||
|
||||
public virtual void When(object @event) { }
|
||||
|
||||
public long Version { get; protected set; } = -1;
|
||||
public long Version { get; set; } = -1;
|
||||
|
||||
public TId Id { get; protected set; }
|
||||
}
|
||||
|
||||
@ -1,19 +1,15 @@
|
||||
using BuildingBlocks.Domain.Event;
|
||||
using BuildingBlocks.EventStoreDB.Events;
|
||||
using BuildingBlocks.Domain.Event;
|
||||
|
||||
namespace BuildingBlocks.Domain.Model
|
||||
namespace BuildingBlocks.Domain.Model;
|
||||
|
||||
public interface IAggregate : IEntity
|
||||
{
|
||||
public interface IAggregate : IProjection, IEntity
|
||||
{
|
||||
IReadOnlyList<IDomainEvent> DomainEvents { get; }
|
||||
IEvent[] ClearDomainEvents();
|
||||
long Version { get; }
|
||||
}
|
||||
|
||||
public interface IAggregate<out T> : IAggregate
|
||||
{
|
||||
T Id { get; }
|
||||
}
|
||||
IReadOnlyList<IDomainEvent> DomainEvents { get; }
|
||||
IEvent[] ClearDomainEvents();
|
||||
long Version { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public interface IAggregate<out T> : IAggregate
|
||||
{
|
||||
T Id { get; }
|
||||
}
|
||||
|
||||
@ -111,11 +111,13 @@ 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:
|
||||
entry.Entity.LastModifiedBy = userId;
|
||||
entry.Entity.LastModified = DateTime.Now;
|
||||
entry.Entity.Version++;
|
||||
break;
|
||||
|
||||
case EntityState.Deleted:
|
||||
|
||||
@ -0,0 +1,32 @@
|
||||
using BuildingBlocks.Domain.Event;
|
||||
using BuildingBlocks.Domain.Model;
|
||||
|
||||
namespace BuildingBlocks.EventStoreDB.Events
|
||||
{
|
||||
public abstract class AggregateEventSourcing<TId> : Entity, IAggregateEventSourcing<TId>
|
||||
{
|
||||
private readonly List<IDomainEvent> _domainEvents = new();
|
||||
public IReadOnlyList<IDomainEvent> DomainEvents => _domainEvents.AsReadOnly();
|
||||
|
||||
public void AddDomainEvent(IDomainEvent domainEvent)
|
||||
{
|
||||
_domainEvents.Add(domainEvent);
|
||||
}
|
||||
|
||||
public IEvent[] ClearDomainEvents()
|
||||
{
|
||||
IEvent[] dequeuedEvents = _domainEvents.ToArray();
|
||||
|
||||
_domainEvents.Clear();
|
||||
|
||||
return dequeuedEvents;
|
||||
}
|
||||
|
||||
public virtual void When(object @event) { }
|
||||
|
||||
public long Version { get; protected set; } = -1;
|
||||
|
||||
public TId Id { get; protected set; }
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,19 @@
|
||||
using BuildingBlocks.Domain.Event;
|
||||
using BuildingBlocks.Domain.Model;
|
||||
|
||||
namespace BuildingBlocks.EventStoreDB.Events
|
||||
{
|
||||
public interface IAggregateEventSourcing : IProjection, IEntity
|
||||
{
|
||||
IReadOnlyList<IDomainEvent> DomainEvents { get; }
|
||||
IEvent[] ClearDomainEvents();
|
||||
long Version { get; }
|
||||
}
|
||||
|
||||
public interface IAggregateEventSourcing<out T> : IAggregateEventSourcing
|
||||
{
|
||||
T Id { get; }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,11 +1,10 @@
|
||||
using BuildingBlocks.Domain.Model;
|
||||
using BuildingBlocks.EventStoreDB.Events;
|
||||
using BuildingBlocks.EventStoreDB.Events;
|
||||
using BuildingBlocks.EventStoreDB.Serialization;
|
||||
using EventStore.Client;
|
||||
|
||||
namespace BuildingBlocks.EventStoreDB.Repository;
|
||||
|
||||
public interface IEventStoreDBRepository<T> where T : class, IAggregate<long>
|
||||
public interface IEventStoreDBRepository<T> where T : class, IAggregateEventSourcing<long>
|
||||
{
|
||||
Task<T?> Find(long id, CancellationToken cancellationToken);
|
||||
Task<ulong> Add(T aggregate, CancellationToken cancellationToken);
|
||||
@ -13,7 +12,7 @@ public interface IEventStoreDBRepository<T> where T : class, IAggregate<long>
|
||||
Task<ulong> Delete(T aggregate, long? expectedRevision = null, CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
||||
public class EventStoreDBRepository<T>: IEventStoreDBRepository<T> where T : class, IAggregate<long>
|
||||
public class EventStoreDBRepository<T>: IEventStoreDBRepository<T> where T : class, IAggregateEventSourcing<long>
|
||||
{
|
||||
private readonly EventStoreClient eventStore;
|
||||
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using BuildingBlocks.Domain.Model;
|
||||
using BuildingBlocks.EventStoreDB.Events;
|
||||
using BuildingBlocks.Exception;
|
||||
|
||||
namespace BuildingBlocks.EventStoreDB.Repository;
|
||||
@ -9,7 +10,7 @@ public static class RepositoryExtensions
|
||||
this IEventStoreDBRepository<T> repository,
|
||||
long id,
|
||||
CancellationToken cancellationToken
|
||||
) where T : class, IAggregate<long>
|
||||
) where T : class, IAggregateEventSourcing<long>
|
||||
{
|
||||
var entity = await repository.Find(id, cancellationToken);
|
||||
|
||||
@ -22,7 +23,7 @@ public static class RepositoryExtensions
|
||||
Action<T> action,
|
||||
long? expectedVersion = null,
|
||||
CancellationToken cancellationToken = default
|
||||
) where T : class, IAggregate<long>
|
||||
) where T : class, IAggregateEventSourcing<long>
|
||||
{
|
||||
var entity = await repository.Get(id, cancellationToken);
|
||||
|
||||
|
||||
@ -1,10 +1,11 @@
|
||||
using Booking.Booking.Events.Domain;
|
||||
using Booking.Booking.Models.ValueObjects;
|
||||
using BuildingBlocks.Domain.Model;
|
||||
using BuildingBlocks.EventStoreDB.Events;
|
||||
|
||||
namespace Booking.Booking.Models;
|
||||
|
||||
public class Booking : Aggregate<long>
|
||||
public class Booking : AggregateEventSourcing<long>
|
||||
{
|
||||
public Booking()
|
||||
{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user