Skip to content

Commit 148b4ee

Browse files
feature: drop the processor, just add the previous state to the transaction command
we have already loaded it, no need to load it again
1 parent 6a4d0ef commit 148b4ee

File tree

14 files changed

+69
-110
lines changed

14 files changed

+69
-110
lines changed

src/EntityDb.Abstractions/Transactions/ITransactionCommand.cs

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,23 +11,30 @@ namespace EntityDb.Abstractions.Transactions
1111
/// <typeparam name="TEntity">The type of entity to be modified.</typeparam>
1212
public interface ITransactionCommand<TEntity>
1313
{
14+
/// <summary>
15+
/// A snapshot of the entity before the command.
16+
/// </summary>
17+
TEntity PreviousEntitySnapshot { get; }
18+
19+
/// <summary>
20+
/// The previous version number of the entity.
21+
/// </summary>
22+
ulong PreviousEntityVersionNumber { get; }
23+
1424
/// <summary>
1525
/// A snapshot of the entity after the command.
1626
/// </summary>
17-
TEntity EntitySnapshot { get; }
27+
TEntity NextEntitySnapshot { get; }
1828

1929
/// <summary>
20-
/// The id of the entity.
30+
/// The next version number of the entity.
2131
/// </summary>
22-
Guid EntityId { get; }
32+
ulong NextEntityVersionNumber { get; }
2333

2434
/// <summary>
25-
/// The previous version number of the entity.
35+
/// The id of the entity.
2636
/// </summary>
27-
/// <remarks>
28-
/// The repository must expect the last command committed to have VersionNumber equal to <see cref="EntityVersionNumber" /> - 1.
29-
/// </remarks>
30-
ulong EntityVersionNumber { get; }
37+
Guid EntityId { get; }
3138

3239
/// <summary>
3340
/// The intent.

src/EntityDb.Common.Tests/EntityDb.Common.Tests.csproj

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,12 @@
2020
</PropertyGroup>
2121

2222
<ItemGroup>
23-
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0"/>
24-
<PackageReference Include="Moq" Version="4.16.1"/>
25-
<PackageReference Include="Shouldly" Version="4.0.3"/>
26-
<PackageReference Include="xunit" Version="2.4.1"/>
27-
<PackageReference Include="Xunit.DependencyInjection" Version="7.6.0"/>
28-
<PackageReference Include="Xunit.DependencyInjection.Logging" Version="7.5.1"/>
23+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
24+
<PackageReference Include="Moq" Version="4.16.1" />
25+
<PackageReference Include="Shouldly" Version="4.0.3" />
26+
<PackageReference Include="xunit" Version="2.4.1" />
27+
<PackageReference Include="Xunit.DependencyInjection" Version="7.6.0" />
28+
<PackageReference Include="Xunit.DependencyInjection.Logging" Version="7.5.1" />
2929
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
3030
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
3131
<PrivateAssets>all</PrivateAssets>
@@ -37,7 +37,7 @@
3737
</ItemGroup>
3838

3939
<ItemGroup>
40-
<ProjectReference Include="..\EntityDb.TestImplementations\EntityDb.TestImplementations.csproj"/>
40+
<ProjectReference Include="..\EntityDb.TestImplementations\EntityDb.TestImplementations.csproj" />
4141
</ItemGroup>
4242

4343
</Project>

src/EntityDb.Common.Tests/Extensions/IEntityRepositoryExtensions.cs

Lines changed: 0 additions & 53 deletions
This file was deleted.

src/EntityDb.Common.Tests/Transactions/TransactionBuilderTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ public void GivenNonExistingEntityId_WhenUsingValidVersioningStrategy_ThenVersio
295295

296296
for (ulong i = 1; i <= NumberOfVersionsToTest; i++)
297297
{
298-
transaction.Commands[(int)(i-1)].EntityVersionNumber.ShouldBe(i);
298+
transaction.Commands[(int)(i-1)].NextEntityVersionNumber.ShouldBe(i);
299299
}
300300
}
301301

src/EntityDb.Common.Tests/Transactions/TransactionTestsBase.cs

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -420,9 +420,9 @@ public async Task GivenReadOnlyMode_WhenPuttingTransaction_ThenThrow()
420420
{
421421
new TransactionCommand<TransactionEntity>
422422
{
423-
EntitySnapshot = default!,
423+
NextEntitySnapshot = default!,
424424
EntityId = Guid.NewGuid(),
425-
EntityVersionNumber = 1,
425+
NextEntityVersionNumber = 1,
426426
Command = new DoNothing(),
427427
Leases = new TransactionMetaData<ILease>(),
428428
Tags = new TransactionMetaData<ITag>()
@@ -456,9 +456,9 @@ static ITransaction<TransactionEntity> NewTransaction(Guid transactionId)
456456
{
457457
new TransactionCommand<TransactionEntity>
458458
{
459-
EntitySnapshot = default!,
459+
NextEntitySnapshot = default!,
460460
EntityId = Guid.NewGuid(),
461-
EntityVersionNumber = 1,
461+
NextEntityVersionNumber = 1,
462462
Command = new DoNothing(),
463463
Leases = new TransactionMetaData<ILease>(),
464464
Tags = new TransactionMetaData<ITag>()
@@ -497,18 +497,18 @@ public async Task GivenNonUniqueVersionNumbers_WhenInsertingCommands_ThenReturnF
497497
{
498498
new TransactionCommand<TransactionEntity>
499499
{
500-
EntitySnapshot = default!,
500+
NextEntitySnapshot = default!,
501501
EntityId = entityId,
502-
EntityVersionNumber = entityVersionNumber,
502+
NextEntityVersionNumber = entityVersionNumber,
503503
Command = new DoNothing(),
504504
Leases = new TransactionMetaData<ILease>(),
505505
Tags = new TransactionMetaData<ITag>()
506506
},
507507
new TransactionCommand<TransactionEntity>
508508
{
509-
EntitySnapshot = default!,
509+
NextEntitySnapshot = default!,
510510
EntityId = entityId,
511-
EntityVersionNumber = entityVersionNumber,
511+
NextEntityVersionNumber = entityVersionNumber,
512512
Command = new DoNothing(),
513513
Leases = new TransactionMetaData<ILease>(),
514514
Tags = new TransactionMetaData<ITag>()
@@ -552,9 +552,9 @@ public async Task
552552
{
553553
new TransactionCommand<TransactionEntity>
554554
{
555-
EntitySnapshot = default!,
555+
NextEntitySnapshot = default!,
556556
EntityId = entityId,
557-
EntityVersionNumber = entityVersionNumber,
557+
NextEntityVersionNumber = entityVersionNumber,
558558
Command = new DoNothing(),
559559
Leases = new TransactionMetaData<ILease>(),
560560
Tags = new TransactionMetaData<ITag>()
@@ -597,9 +597,9 @@ static ITransaction<TransactionEntity> NewTransaction(Guid entityId, ulong entit
597597
{
598598
new TransactionCommand<TransactionEntity>
599599
{
600-
EntitySnapshot = default!,
600+
NextEntitySnapshot = default!,
601601
EntityId = entityId,
602-
EntityVersionNumber = entityVersionNumber,
602+
NextEntityVersionNumber = entityVersionNumber,
603603
Command = new DoNothing(),
604604
Leases = new TransactionMetaData<ILease>(),
605605
Tags = new TransactionMetaData<ITag>()
@@ -647,9 +647,9 @@ public async Task GivenNonUniqueTags_WhenInsertingTagDocuments_ThenReturnTrue()
647647
{
648648
new TransactionCommand<TransactionEntity>
649649
{
650-
EntitySnapshot = default!,
650+
NextEntitySnapshot = default!,
651651
EntityId = Guid.NewGuid(),
652-
EntityVersionNumber = 1,
652+
NextEntityVersionNumber = 1,
653653
Command = new DoNothing(),
654654
Leases = new TransactionMetaData<ILease>(),
655655
Tags = new TransactionMetaData<ITag>
@@ -659,9 +659,9 @@ public async Task GivenNonUniqueTags_WhenInsertingTagDocuments_ThenReturnTrue()
659659
},
660660
new TransactionCommand<TransactionEntity>
661661
{
662-
EntitySnapshot = default!,
662+
NextEntitySnapshot = default!,
663663
EntityId = Guid.NewGuid(),
664-
EntityVersionNumber = 1,
664+
NextEntityVersionNumber = 1,
665665
Command = new DoNothing(),
666666
Leases = new TransactionMetaData<ILease>(),
667667
Tags = new TransactionMetaData<ITag>
@@ -699,9 +699,9 @@ public async Task GivenNonUniqueLeases_WhenInsertingLeaseDocuments_ThenReturnFal
699699
{
700700
new TransactionCommand<TransactionEntity>
701701
{
702-
EntitySnapshot = default!,
702+
NextEntitySnapshot = default!,
703703
EntityId = Guid.NewGuid(),
704-
EntityVersionNumber = 1,
704+
NextEntityVersionNumber = 1,
705705
Command = new DoNothing(),
706706
Leases = new TransactionMetaData<ILease>
707707
{
@@ -711,9 +711,9 @@ public async Task GivenNonUniqueLeases_WhenInsertingLeaseDocuments_ThenReturnFal
711711
},
712712
new TransactionCommand<TransactionEntity>
713713
{
714-
EntitySnapshot = default!,
714+
NextEntitySnapshot = default!,
715715
EntityId = Guid.NewGuid(),
716-
EntityVersionNumber = 1,
716+
NextEntityVersionNumber = 1,
717717
Command = new DoNothing(),
718718
Leases = new TransactionMetaData<ILease>
719719
{
@@ -912,7 +912,7 @@ public async Task GivenTransactionCreatesEntity_WhenQueryingForVersionOne_ThenRe
912912

913913
transaction.Commands.Length.ShouldBe(1);
914914

915-
transaction.Commands[0].EntityVersionNumber.ShouldBe(1ul);
915+
transaction.Commands[0].NextEntityVersionNumber.ShouldBe(1ul);
916916

917917
newCommands.Length.ShouldBe(1);
918918

@@ -955,7 +955,7 @@ public async Task
955955

956956
secondTransaction.Commands.Length.ShouldBe(1);
957957

958-
secondTransaction.Commands[0].EntityVersionNumber.ShouldBe(2ul);
958+
secondTransaction.Commands[0].NextEntityVersionNumber.ShouldBe(2ul);
959959

960960
newCommands.Length.ShouldBe(1);
961961

src/EntityDb.Common/Exceptions/OptimisticConcurrencyException.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ namespace EntityDb.Common.Exceptions
77
/// <summary>
88
/// The exception that is logged when an actor passes a <see cref="ITransaction{TEntity}" /> to an
99
/// <see cref="ITransactionRepository{TEntity}" /> with a
10-
/// <see cref="ITransactionCommand{TEntity}.EntityVersionNumber" /> that is not the next number
11-
/// after the previous version number.
10+
/// <see cref="ITransactionCommand{TEntity}.PreviousEntityVersionNumber" /> that is not the actual
11+
/// previous version number.
1212
/// </summary>
1313
/// <remarks>
1414
/// A program will not be able to catch this exception if it is thrown.
@@ -18,14 +18,14 @@ namespace EntityDb.Common.Exceptions
1818
public sealed class OptimisticConcurrencyException : Exception
1919
{
2020
/// <summary>
21-
/// Throws a new <see cref="OptimisticConcurrencyException" /> if <paramref name="nextVersionNumber" />
22-
/// is not the next number after <paramref name="previousVersionNumber" />.
21+
/// Throws a new <see cref="OptimisticConcurrencyException" /> if <paramref name="actualPreviousVersionNumber" />
22+
/// is not equal to <paramref name="expectedPreviousVersionNumber" />.
2323
/// </summary>
24-
/// <param name="previousVersionNumber">The previous version number.</param>
25-
/// <param name="nextVersionNumber">The next version number.</param>
26-
public static void ThrowIfDiscontinuous(ulong previousVersionNumber, ulong nextVersionNumber)
24+
/// <param name="expectedPreviousVersionNumber">The expected previous version number.</param>
25+
/// <param name="actualPreviousVersionNumber">The actual previous version number.</param>
26+
public static void ThrowIfMismatch(ulong expectedPreviousVersionNumber, ulong actualPreviousVersionNumber)
2727
{
28-
if (nextVersionNumber != previousVersionNumber + 1)
28+
if (expectedPreviousVersionNumber != actualPreviousVersionNumber)
2929
{
3030
throw new OptimisticConcurrencyException();
3131
}

src/EntityDb.Common/Exceptions/VersionZeroReservedException.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ namespace EntityDb.Common.Exceptions
66
/// <summary>
77
/// The exception that is thrown when an actor passes an <see cref="ITransaction{TEntity}" /> to
88
/// <see cref="ITransactionRepository{TEntity}.PutTransaction(ITransaction{TEntity})" /> with any
9-
/// <see cref="ITransactionCommand{TEntity}.EntityVersionNumber"/> equal to zero.
9+
/// <see cref="ITransactionCommand{TEntity}.NextEntityVersionNumber"/> equal to zero.
1010
/// </summary>
1111
/// <remarks>
1212
/// Version Zero is reserved for an entity that has not yet been created/persisted.

src/EntityDb.Common/Transactions/SnapshottingTransactionSubscriber.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ protected override async Task NotifyAsync(ITransaction<TEntity> transaction)
3030
foreach (var commandGroup in commandGroups)
3131
{
3232
var entityId = commandGroup.Key;
33-
var nextSnapshot = commandGroup.Last().EntitySnapshot;
33+
var nextSnapshot = commandGroup.Last().NextEntitySnapshot;
3434

3535
await using var snapshotRepository =
3636
await _snapshotRepositoryFactory.CreateRepository(_snapshotSessionOptions);

src/EntityDb.Common/Transactions/TransactionBuilder.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ private ITag[] GetTags(TEntity entity)
7979
private void AddTransactionCommand(Guid entityId, ICommand<TEntity> command)
8080
{
8181
var previousEntity = _knownEntities[entityId];
82+
var previousEntityVersionNumber = _versioningStrategy.GetVersionNumber(previousEntity);
8283

8384
CommandNotAuthorizedException.ThrowIfFalse(IsAuthorized(previousEntity, command));
8485

@@ -87,9 +88,11 @@ private void AddTransactionCommand(Guid entityId, ICommand<TEntity> command)
8788

8889
_transactionCommands.Add(new TransactionCommand<TEntity>
8990
{
90-
EntitySnapshot = nextEntity,
91+
PreviousEntitySnapshot = previousEntity,
92+
PreviousEntityVersionNumber = previousEntityVersionNumber,
93+
NextEntitySnapshot = nextEntity,
94+
NextEntityVersionNumber = nextEntityVersionNumber,
9195
EntityId = entityId,
92-
EntityVersionNumber = nextEntityVersionNumber,
9396
Command = command,
9497
Leases = GetTransactionMetaData(previousEntity, nextEntity, GetLeases),
9598
Tags = GetTransactionMetaData(previousEntity, nextEntity, GetTags)

src/EntityDb.Common/Transactions/TransactionCommand.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@ namespace EntityDb.Common.Transactions
88
{
99
internal sealed record TransactionCommand<TEntity> : ITransactionCommand<TEntity>
1010
{
11-
public TEntity EntitySnapshot { get; init; } = default!;
11+
public TEntity PreviousEntitySnapshot { get; init; } = default!;
12+
public ulong PreviousEntityVersionNumber { get; init; }
13+
public TEntity NextEntitySnapshot { get; init; } = default!;
14+
public ulong NextEntityVersionNumber { get; init; }
1215
public Guid EntityId { get; init; }
13-
public ulong EntityVersionNumber { get; init; }
1416
public ICommand<TEntity> Command { get; init; } = default!;
1517
public ITransactionMetaData<ILease> Leases { get; init; } = default!;
1618
public ITransactionMetaData<ITag> Tags { get; init; } = default!;

0 commit comments

Comments
 (0)