Skip to content

Commit

Permalink
Added solutions for Optimistic Concurrency
Browse files Browse the repository at this point in the history
  • Loading branch information
oskardudycz committed May 1, 2024
1 parent 4fa009e commit 71072de
Show file tree
Hide file tree
Showing 52 changed files with 2,047 additions and 1,251 deletions.
7 changes: 7 additions & 0 deletions EventSourcing.NetCore.sln
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "08-ApplicationLogic.Marten.
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "10-OptimisticConcurrency.Marten.Tests", "Workshops\IntroductionToEventSourcing\10-OptimisticConcurrency.Marten.Tests\10-OptimisticConcurrency.Marten.Tests.csproj", "{E03F9212-A1C3-4E3A-8DB6-C2FE05130C03}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "10-OptimisticConcurrency.Marten.Tests", "Workshops\IntroductionToEventSourcing\Solved\10-OptimisticConcurrency.Marten.Tests\10-OptimisticConcurrency.Marten.Tests.csproj", "{44BE49F6-8F70-48B7-8AC0-4B99DF855341}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -1015,6 +1017,10 @@ Global
{E03F9212-A1C3-4E3A-8DB6-C2FE05130C03}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E03F9212-A1C3-4E3A-8DB6-C2FE05130C03}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E03F9212-A1C3-4E3A-8DB6-C2FE05130C03}.Release|Any CPU.Build.0 = Release|Any CPU
{44BE49F6-8F70-48B7-8AC0-4B99DF855341}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{44BE49F6-8F70-48B7-8AC0-4B99DF855341}.Debug|Any CPU.Build.0 = Debug|Any CPU
{44BE49F6-8F70-48B7-8AC0-4B99DF855341}.Release|Any CPU.ActiveCfg = Release|Any CPU
{44BE49F6-8F70-48B7-8AC0-4B99DF855341}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -1201,6 +1207,7 @@ Global
{62FE6E28-7226-4CFB-A9F7-1B532FDEE6F9} = {65F6E2BE-B2D4-4E56-B0CB-3062C4882B9E}
{9A07F586-2D4B-46F4-AF8F-AF8290AE4A73} = {65F6E2BE-B2D4-4E56-B0CB-3062C4882B9E}
{E03F9212-A1C3-4E3A-8DB6-C2FE05130C03} = {14C7B928-9D6C-441A-8A1F-0C49173E73EB}
{44BE49F6-8F70-48B7-8AC0-4B99DF855341} = {65F6E2BE-B2D4-4E56-B0CB-3062C4882B9E}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {A5F55604-2FF3-43B7-B657-4F18E6E95D3B}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@
{
var exception = context.Features.Get<IExceptionHandlerPathFeature>()?.Error;
Console.WriteLine("ERROR: " + exception);
context.Response.StatusCode = exception switch
{
ArgumentException => StatusCodes.Status400BadRequest,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public class AddProductItemToShoppingCartTests(ApiSpecification<Program> api):
IClassFixture<ApiSpecification<Program>>
{
[Theory]
[Trait("Category", "SkipCI")]
[InlineData("immutable")]
[InlineData("mutable")]
[InlineData("mixed")]
Expand All @@ -20,11 +21,13 @@ public Task CantAddProductItemToNotExistingShoppingCart(string apiPrefix) =>
.When(
POST,
URI(ShoppingCartProductItemsUrl(apiPrefix, ClientId, NotExistingShoppingCartId)),
BODY(new AddProductRequest(ProductItem))
BODY(new AddProductRequest(ProductItem)),
HEADERS(IF_MATCH(0))
)
.Then(NOT_FOUND);

[Theory]
[Trait("Category", "SkipCI")]
[InlineData("immutable")]
[InlineData("mutable")]
[InlineData("mixed")]
Expand All @@ -39,13 +42,14 @@ public Task AddsProductItemToEmptyShoppingCart(string apiPrefix) =>
.Then(NO_CONTENT, RESPONSE_ETAG_HEADER(2));

[Theory]
[Trait("Category", "SkipCI")]
[InlineData("immutable")]
[InlineData("mutable")]
[InlineData("mixed")]
public Task AddsProductItemToNonEmptyShoppingCart(string apiPrefix) =>
api.Given(
OpenedShoppingCart(apiPrefix, ClientId),
WithProductItem(apiPrefix, ClientId, ProductItem)
WithProductItem(apiPrefix, ClientId, ProductItem, 1)
)
.When(
POST,
Expand All @@ -56,14 +60,15 @@ public Task AddsProductItemToNonEmptyShoppingCart(string apiPrefix) =>
.Then(NO_CONTENT, RESPONSE_ETAG_HEADER(3));

[Theory]
[Trait("Category", "SkipCI")]
[InlineData("immutable")]
[InlineData("mutable")]
[InlineData("mixed")]
public Task CantAddProductItemToConfirmedShoppingCart(string apiPrefix) =>
api.Given(
OpenedShoppingCart(apiPrefix, ClientId),
WithProductItem(apiPrefix, ClientId, ProductItem),
ThenConfirmed(apiPrefix, ClientId)
WithProductItem(apiPrefix, ClientId, ProductItem, 1),
ThenConfirmed(apiPrefix, ClientId, 2)
)
.When(
POST,
Expand All @@ -74,14 +79,15 @@ public Task CantAddProductItemToConfirmedShoppingCart(string apiPrefix) =>
.Then(CONFLICT);

[Theory]
[Trait("Category", "SkipCI")]
[InlineData("immutable")]
[InlineData("mutable")]
[InlineData("mixed")]
public Task CantAddProductItemToCanceledShoppingCart(string apiPrefix) =>
api.Given(
OpenedShoppingCart(apiPrefix, ClientId),
WithProductItem(apiPrefix, ClientId, ProductItem),
ThenCanceled(apiPrefix, ClientId)
WithProductItem(apiPrefix, ClientId, ProductItem, 1),
ThenCanceled(apiPrefix, ClientId, 2)
)
.When(
POST,
Expand All @@ -92,13 +98,14 @@ public Task CantAddProductItemToCanceledShoppingCart(string apiPrefix) =>
.Then(CONFLICT);

[Theory]
[Trait("Category", "SkipCI")]
[InlineData("immutable")]
[InlineData("mutable")]
[InlineData("mixed")]
public Task ReturnsNonEmptyShoppingCart(string apiPrefix) =>
api.Given(
OpenedShoppingCart(apiPrefix, ClientId),
WithProductItem(apiPrefix, ClientId, ProductItem)
WithProductItem(apiPrefix, ClientId, ProductItem, 1)
)
.When(GET, URI(ctx => ShoppingCartUrl(apiPrefix, ClientId, ctx.GetCreatedId<Guid>())))
.Then(OK, RESPONSE_ETAG_HEADER(2));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,28 @@ public class CancelShoppingCartTests(ApiSpecification<Program> api):
IClassFixture<ApiSpecification<Program>>
{
[Theory]
[Trait("Category", "SkipCI")]
[InlineData("immutable")]
[InlineData("mutable")]
[InlineData("mixed")]
public Task CantCancelNotExistingShoppingCart(string apiPrefix) =>
api.Given()
.When(
DELETE,
URI(ShoppingCartUrl(apiPrefix, ClientId, NotExistingShoppingCartId))
URI(ShoppingCartUrl(apiPrefix, ClientId, NotExistingShoppingCartId)),
HEADERS(IF_MATCH(0))
)
.Then(NOT_FOUND);

[Theory]
[Trait("Category", "SkipCI")]
[InlineData("immutable")]
[InlineData("mutable")]
[InlineData("mixed")]
public Task CancelsNonEmptyShoppingCart(string apiPrefix) =>
api.Given(
OpenedShoppingCart(apiPrefix, ClientId),
WithProductItem(apiPrefix, ClientId, ProductItem)
WithProductItem(apiPrefix, ClientId, ProductItem, 1)
)
.When(
DELETE,
Expand All @@ -40,14 +43,15 @@ public Task CancelsNonEmptyShoppingCart(string apiPrefix) =>
.Then(NO_CONTENT, RESPONSE_ETAG_HEADER(3));

[Theory]
[Trait("Category", "SkipCI")]
[InlineData("immutable")]
[InlineData("mutable")]
[InlineData("mixed")]
public Task CantCancelAlreadyCanceledShoppingCart(string apiPrefix) =>
api.Given(
OpenedShoppingCart(apiPrefix, ClientId),
WithProductItem(apiPrefix, ClientId, ProductItem),
ThenCanceled(apiPrefix, ClientId)
WithProductItem(apiPrefix, ClientId, ProductItem, 1),
ThenCanceled(apiPrefix, ClientId, 2)
)
.When(
DELETE,
Expand All @@ -57,14 +61,15 @@ public Task CantCancelAlreadyCanceledShoppingCart(string apiPrefix) =>
.Then(CONFLICT);

[Theory]
[Trait("Category", "SkipCI")]
[InlineData("immutable")]
[InlineData("mutable")]
[InlineData("mixed")]
public Task CantCancelConfirmedShoppingCart(string apiPrefix) =>
api.Given(
OpenedShoppingCart(apiPrefix, ClientId),
WithProductItem(apiPrefix, ClientId, ProductItem),
ThenConfirmed(apiPrefix, ClientId)
WithProductItem(apiPrefix, ClientId, ProductItem, 1),
ThenConfirmed(apiPrefix, ClientId, 2)
)
.When(
DELETE,
Expand All @@ -74,14 +79,15 @@ public Task CantCancelConfirmedShoppingCart(string apiPrefix) =>
.Then(CONFLICT);

[Theory]
[Trait("Category", "SkipCI")]
[InlineData("immutable")]
[InlineData("mutable")]
[InlineData("mixed")]
public Task ReturnsNonEmptyShoppingCart(string apiPrefix) =>
api.Given(
OpenedShoppingCart(apiPrefix, ClientId),
WithProductItem(apiPrefix, ClientId, ProductItem),
ThenCanceled(apiPrefix, ClientId)
WithProductItem(apiPrefix, ClientId, ProductItem, 1),
ThenCanceled(apiPrefix, ClientId, 2)
)
.When(GET, URI(ctx => ShoppingCartUrl(apiPrefix, ClientId, ctx.GetCreatedId<Guid>())))
.Then(OK, RESPONSE_ETAG_HEADER(3));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,21 @@ public class ConfirmShoppingCartTests(ApiSpecification<Program> api):
IClassFixture<ApiSpecification<Program>>
{
[Theory]
[Trait("Category", "SkipCI")]
[InlineData("immutable")]
[InlineData("mutable")]
[InlineData("mixed")]
public Task CantConfirmNotExistingShoppingCart(string apiPrefix) =>
api.Given()
.When(
POST,
URI(ConfirmShoppingCartUrl(apiPrefix, ClientId, NotExistingShoppingCartId))
URI(ConfirmShoppingCartUrl(apiPrefix, ClientId, NotExistingShoppingCartId)),
HEADERS(IF_MATCH(0))
)
.Then(NOT_FOUND);

[Theory]
[Trait("Category", "SkipCI")]
[InlineData("immutable")]
[InlineData("mutable")]
[InlineData("mixed")]
Expand All @@ -37,13 +40,14 @@ public Task CantConfirmEmptyShoppingCart(string apiPrefix) =>
.Then(CONFLICT);

[Theory]
[Trait("Category", "SkipCI")]
[InlineData("immutable")]
[InlineData("mutable")]
[InlineData("mixed")]
public Task ConfirmsNonEmptyShoppingCart(string apiPrefix) =>
api.Given(
OpenedShoppingCart(apiPrefix, ClientId),
WithProductItem(apiPrefix, ClientId, ProductItem)
WithProductItem(apiPrefix, ClientId, ProductItem, 1)
)
.When(
POST,
Expand All @@ -53,14 +57,15 @@ public Task ConfirmsNonEmptyShoppingCart(string apiPrefix) =>
.Then(NO_CONTENT, RESPONSE_ETAG_HEADER(3));

[Theory]
[Trait("Category", "SkipCI")]
[InlineData("immutable")]
[InlineData("mutable")]
[InlineData("mixed")]
public Task CantConfirmAlreadyConfirmedShoppingCart(string apiPrefix) =>
api.Given(
OpenedShoppingCart(apiPrefix, ClientId),
WithProductItem(apiPrefix, ClientId, ProductItem),
ThenConfirmed(apiPrefix, ClientId)
WithProductItem(apiPrefix, ClientId, ProductItem, 1),
ThenConfirmed(apiPrefix, ClientId, 2)
)
.When(
POST,
Expand All @@ -70,14 +75,15 @@ public Task CantConfirmAlreadyConfirmedShoppingCart(string apiPrefix) =>
.Then(CONFLICT);

[Theory]
[Trait("Category", "SkipCI")]
[InlineData("immutable")]
[InlineData("mutable")]
[InlineData("mixed")]
public Task CantConfirmCanceledShoppingCart(string apiPrefix) =>
api.Given(
OpenedShoppingCart(apiPrefix, ClientId),
WithProductItem(apiPrefix, ClientId, ProductItem),
ThenCanceled(apiPrefix, ClientId)
WithProductItem(apiPrefix, ClientId, ProductItem, 1),
ThenCanceled(apiPrefix, ClientId, 2)
)
.When(
POST,
Expand All @@ -87,14 +93,15 @@ public Task CantConfirmCanceledShoppingCart(string apiPrefix) =>
.Then(CONFLICT);

[Theory]
[Trait("Category", "SkipCI")]
[InlineData("immutable")]
[InlineData("mutable")]
[InlineData("mixed")]
public Task ReturnsNonEmptyShoppingCart(string apiPrefix) =>
api.Given(
OpenedShoppingCart(apiPrefix, ClientId),
WithProductItem(apiPrefix, ClientId, ProductItem),
ThenConfirmed(apiPrefix, ClientId)
WithProductItem(apiPrefix, ClientId, ProductItem, 1),
ThenConfirmed(apiPrefix, ClientId, 2)
)
.When(GET, URI(ctx => ShoppingCartUrl(apiPrefix, ClientId, ctx.GetCreatedId<Guid>())))
.Then(OK, RESPONSE_ETAG_HEADER(3));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,22 +30,25 @@ public static class Scenarios
public static RequestDefinition OpenedShoppingCart(string apiPrefix, Guid clientId) =>
SEND(POST, URI(Fixtures.ShoppingCartsUrl(apiPrefix, clientId)));

public static RequestDefinition WithProductItem(string apiPrefix, Guid clientId, ProductItemRequest productItem) =>
public static RequestDefinition WithProductItem(string apiPrefix, Guid clientId, ProductItemRequest productItem, int ifMatch) =>
SEND(
POST,
URI(ctx => Fixtures.ShoppingCartProductItemsUrl(apiPrefix, clientId, ctx.GetCreatedId<Guid>())),
BODY(new AddProductRequest(productItem))
BODY(new AddProductRequest(productItem)),
HEADERS(IF_MATCH(ifMatch))
);

public static RequestDefinition ThenConfirmed(string apiPrefix, Guid clientId) =>
public static RequestDefinition ThenConfirmed(string apiPrefix, Guid clientId, int ifMatch) =>
SEND(
POST,
URI(ctx => Fixtures.ConfirmShoppingCartUrl(apiPrefix, clientId, ctx.GetCreatedId<Guid>()))
URI(ctx => Fixtures.ConfirmShoppingCartUrl(apiPrefix, clientId, ctx.GetCreatedId<Guid>())),
HEADERS(IF_MATCH(ifMatch))
);

public static RequestDefinition ThenCanceled(string apiPrefix, Guid clientId) =>
public static RequestDefinition ThenCanceled(string apiPrefix, Guid clientId, int ifMatch) =>
SEND(
DELETE,
URI(ctx => Fixtures.ShoppingCartUrl(apiPrefix, clientId, ctx.GetCreatedId<Guid>()))
URI(ctx => Fixtures.ShoppingCartUrl(apiPrefix, clientId, ctx.GetCreatedId<Guid>())),
HEADERS(IF_MATCH(ifMatch))
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ public class OpenShoppingCartTests(ApiSpecification<Program> api):
IClassFixture<ApiSpecification<Program>>
{
[Theory]
[Trait("Category", "SkipCI")]
[InlineData("immutable")]
[InlineData("mutable")]
[InlineData("mixed")]
Expand All @@ -22,6 +23,7 @@ public Task OpensShoppingCart(string apiPrefix) =>
);

[Theory]
[Trait("Category", "SkipCI")]
[InlineData("immutable")]
[InlineData("mutable")]
[InlineData("mixed")]
Expand Down
Loading

0 comments on commit 71072de

Please sign in to comment.