From 7bf6fbbdec70683a3ba5a2a9937baa27da811a8e Mon Sep 17 00:00:00 2001 From: Mateusz Nowak Date: Mon, 17 Feb 2025 01:07:00 +0100 Subject: [PATCH 1/3] add compensating action --- .../WhenCreatureRecruitedThenAddToArmyProcessor.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/dddheroes/heroesofddd/creaturerecruitment/automation/WhenCreatureRecruitedThenAddToArmyProcessor.java b/src/main/java/com/dddheroes/heroesofddd/creaturerecruitment/automation/WhenCreatureRecruitedThenAddToArmyProcessor.java index d457f59..242165b 100644 --- a/src/main/java/com/dddheroes/heroesofddd/creaturerecruitment/automation/WhenCreatureRecruitedThenAddToArmyProcessor.java +++ b/src/main/java/com/dddheroes/heroesofddd/creaturerecruitment/automation/WhenCreatureRecruitedThenAddToArmyProcessor.java @@ -1,6 +1,7 @@ package com.dddheroes.heroesofddd.creaturerecruitment.automation; import com.dddheroes.heroesofddd.armies.write.addcreature.AddCreatureToArmy; +import com.dddheroes.heroesofddd.creaturerecruitment.write.changeavailablecreatures.IncreaseAvailableCreatures; import com.dddheroes.heroesofddd.creaturerecruitment.write.recruitcreature.CreatureRecruited; import com.dddheroes.heroesofddd.shared.GameMetaData; import org.axonframework.commandhandling.gateway.CommandGateway; @@ -33,6 +34,15 @@ void react( event.quantity() ); - commandGateway.sendAndWait(command, GameMetaData.with(gameId, playerId)); + try { + commandGateway.sendAndWait(command, GameMetaData.with(gameId, playerId)); + } catch (Exception e) { + var compensatingAction = IncreaseAvailableCreatures.command( + event.dwellingId(), + event.creatureId(), + event.quantity() + ); + commandGateway.sendAndWait(compensatingAction, GameMetaData.with(gameId, playerId)); + } } } From 8e09260e192be6f7ed0ccb784885dcf59b2bf0a1 Mon Sep 17 00:00:00 2001 From: Mateusz Nowak Date: Mon, 17 Feb 2025 01:17:34 +0100 Subject: [PATCH 2/3] WhenCreatureRecruitedThenAddToArmyTest - add compensating action --- ...henCreatureRecruitedThenAddToArmyTest.java | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/src/test/java/com/dddheroes/heroesofddd/creaturerecruitment/automation/WhenCreatureRecruitedThenAddToArmyTest.java b/src/test/java/com/dddheroes/heroesofddd/creaturerecruitment/automation/WhenCreatureRecruitedThenAddToArmyTest.java index 38f8b59..4b7d26d 100644 --- a/src/test/java/com/dddheroes/heroesofddd/creaturerecruitment/automation/WhenCreatureRecruitedThenAddToArmyTest.java +++ b/src/test/java/com/dddheroes/heroesofddd/creaturerecruitment/automation/WhenCreatureRecruitedThenAddToArmyTest.java @@ -1,11 +1,14 @@ package com.dddheroes.heroesofddd.creaturerecruitment.automation; import com.dddheroes.heroesofddd.TestcontainersConfiguration; +import com.dddheroes.heroesofddd.armies.write.ArmyEvent; import com.dddheroes.heroesofddd.armies.write.addcreature.AddCreatureToArmy; +import com.dddheroes.heroesofddd.armies.write.addcreature.CreatureAddedToArmy; import com.dddheroes.heroesofddd.creaturerecruitment.write.DwellingEvent; import com.dddheroes.heroesofddd.creaturerecruitment.write.DwellingId; import com.dddheroes.heroesofddd.creaturerecruitment.write.builddwelling.DwellingBuilt; import com.dddheroes.heroesofddd.creaturerecruitment.write.changeavailablecreatures.AvailableCreaturesChanged; +import com.dddheroes.heroesofddd.creaturerecruitment.write.changeavailablecreatures.IncreaseAvailableCreatures; import com.dddheroes.heroesofddd.creaturerecruitment.write.recruitcreature.CreatureRecruited; import com.dddheroes.heroesofddd.shared.ArmyId; import com.dddheroes.heroesofddd.shared.CreatureIds; @@ -68,6 +71,77 @@ void whenCreatureRecruited_ThenAddCreatureToArmy() { ); } + @Test + void givenArmyIsNotFull_whenCreatureRecruited_ThenAddToTheArmyAndDoNotCompensate() { + // given + var armyId = ArmyId.random().raw(); + givenArmyEvents( + armyId, + new CreatureAddedToArmy(armyId, CreatureIds.angel().raw(), 1), + new CreatureAddedToArmy(armyId, CreatureIds.behemoth().raw(), 1), + new CreatureAddedToArmy(armyId, CreatureIds.bowman().raw(), 1), + new CreatureAddedToArmy(armyId, CreatureIds.redDragon().raw(), 1), + new CreatureAddedToArmy(armyId, CreatureIds.blackDragon().raw(), 1), + new CreatureAddedToArmy(armyId, CreatureIds.archAngel().raw(), 1) + ); + // when + var dwellingId = DwellingId.random().raw(); + var creatureId = CreatureIds.phoenix().raw(); + givenDwellingEvents( + dwellingId, + new DwellingBuilt(dwellingId, creatureId, PHOENIX_COST), + new AvailableCreaturesChanged(dwellingId, creatureId, 3), + new CreatureRecruited(dwellingId, creatureId, armyId, 1, PHOENIX_COST) + ); + + // and + // processed by the automation + + // then + awaitUntilAsserted(() -> verify(commandGateway, times(1)) + .sendAndWait(AddCreatureToArmy.command(armyId, creatureId, 1), gameMetaData()) + ); + awaitUntilAsserted(() -> verify(commandGateway, never()) + .sendAndWait(IncreaseAvailableCreatures.command(dwellingId, creatureId, 2), gameMetaData()) + ); + } + + @Test + void givenArmyIsFull_whenCreatureRecruited_ThenDoNotAddToTheArmyAndCompensateRecruitment() { + // given + var armyId = ArmyId.random().raw(); + givenArmyEvents( + armyId, + new CreatureAddedToArmy(armyId, CreatureIds.angel().raw(), 1), + new CreatureAddedToArmy(armyId, CreatureIds.behemoth().raw(), 1), + new CreatureAddedToArmy(armyId, CreatureIds.bowman().raw(), 1), + new CreatureAddedToArmy(armyId, CreatureIds.redDragon().raw(), 1), + new CreatureAddedToArmy(armyId, CreatureIds.blackDragon().raw(), 1), + new CreatureAddedToArmy(armyId, CreatureIds.archAngel().raw(), 1), + new CreatureAddedToArmy(armyId, CreatureIds.centaur().raw(), 1) + ); + // when + var dwellingId = DwellingId.random().raw(); + var creatureId = CreatureIds.phoenix().raw(); + givenDwellingEvents( + dwellingId, + new DwellingBuilt(dwellingId, creatureId, PHOENIX_COST), + new AvailableCreaturesChanged(dwellingId, creatureId, 3), + new CreatureRecruited(dwellingId, creatureId, armyId, 2, PHOENIX_COST) + ); + + // and + // processed by the automation + + // then + awaitUntilAsserted(() -> verify(commandGateway, never()) + .sendAndWait(AddCreatureToArmy.command(armyId, creatureId, 1), gameMetaData()) + ); + awaitUntilAsserted(() -> verify(commandGateway, times(1)) + .sendAndWait(IncreaseAvailableCreatures.command(dwellingId, creatureId, 2), gameMetaData()) + ); + } + private void givenDwellingEvents(String dwellingId, DwellingEvent... events) { for (int i = 0; i < events.length; i++) { eventGateway.publish(dwellingDomainEvent(dwellingId, i, events[i])); @@ -83,6 +157,22 @@ private DomainEventMessage dwellingDomainEvent(String dwellingId, int sequenc ).andMetaData(gameMetaData()); } + private void givenArmyEvents(String armyId, ArmyEvent... events) { + for (int i = 0; i < events.length; i++) { + eventGateway.publish(armyDomainEvent(armyId, i, events[i])); + } + } + + + private DomainEventMessage armyDomainEvent(String armyId, int sequenceNumber, ArmyEvent payload) { + return new GenericDomainEventMessage<>( + "Army", + armyId, + sequenceNumber, + payload + ).andMetaData(gameMetaData()); + } + private static MetaData gameMetaData() { return GameMetaData.with(GAME_ID, PLAYER_ID); } From 131a7ffb4691874a8b6d91804fec6a8099eb77ae Mon Sep 17 00:00:00 2001 From: Mateusz Nowak Date: Mon, 17 Feb 2025 01:20:25 +0100 Subject: [PATCH 3/3] remove unnecessary logs --- .../read/getalldwellings/GetAllDwellingsTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test/java/com/dddheroes/heroesofddd/creaturerecruitment/read/getalldwellings/GetAllDwellingsTest.java b/src/test/java/com/dddheroes/heroesofddd/creaturerecruitment/read/getalldwellings/GetAllDwellingsTest.java index 5a6cea2..4f68473 100644 --- a/src/test/java/com/dddheroes/heroesofddd/creaturerecruitment/read/getalldwellings/GetAllDwellingsTest.java +++ b/src/test/java/com/dddheroes/heroesofddd/creaturerecruitment/read/getalldwellings/GetAllDwellingsTest.java @@ -81,7 +81,6 @@ void projectingDwellingReadModel_TestCase2() { } private GetAllDwellings getAllDwellings() { - System.out.println("GET ALL DWELLINGS: " + GAME_ID); return GetAllDwellings.query(GAME_ID); }