diff --git a/Mimir.Worker/ActionHandler/CombinationSlotStateHandler.cs b/Mimir.Worker/ActionHandler/CombinationSlotStateHandler.cs index 7972c304..9f199b18 100644 --- a/Mimir.Worker/ActionHandler/CombinationSlotStateHandler.cs +++ b/Mimir.Worker/ActionHandler/CombinationSlotStateHandler.cs @@ -16,7 +16,7 @@ public class CombinationSlotStateHandler(IStateService stateService, MongoDbServ : BaseActionHandler( stateService, store, - "^combination_consumable[0-9]*$|^combination_equipment[0-9]*$|^event_consumable_item_crafts[0-9]*$|^item_enhancement[0-9]*$|^rapid_combination[0-9]*$", + "^combination_consumable[0-9]*$|^combination_equipment[0-9]*$|^event_consumable_item_crafts[0-9]*$|^item_enhancement[0-9]*$", Log.ForContext()) { protected override async Task TryHandleAction( @@ -30,8 +30,7 @@ protected override async Task TryHandleAction( { var e = new InvalidTypeOfActionPlainValueInternalException( [ValueKind.Dictionary], - actionPlainValueInternal?.Kind - ); + actionPlainValueInternal?.Kind); Logger.Fatal( e, "Unexpected actionPlainValueInternal type: {ActionPlainValueInternalType}", @@ -65,11 +64,6 @@ protected override async Task TryHandleAction( avatarAddress = new Address(list[0]); slotIndex = list[3].ToInteger(); } - else if (Regex.IsMatch(actionType, "^rapid_combination[0-9]*$")) - { - avatarAddress = new Address(actionValues["avatarAddress"]); - slotIndex = actionValues["slotIndex"].ToInteger(); - } else { var e = new ArgumentException($"Unknown actionType: {actionType}"); @@ -104,8 +98,7 @@ await Store.UpsertStateDataManyAsync( CollectionNames.GetCollectionName(), [doc], session, - stoppingToken - ); + stoppingToken); return true; } diff --git a/Mimir.Worker/ActionHandler/PetStateHandler.cs b/Mimir.Worker/ActionHandler/PetStateHandler.cs index 0987bfc4..a6fa6ad4 100644 --- a/Mimir.Worker/ActionHandler/PetStateHandler.cs +++ b/Mimir.Worker/ActionHandler/PetStateHandler.cs @@ -1,4 +1,3 @@ -using System.Globalization; using Bencodex.Types; using Lib9c.Models.Extensions; using Libplanet.Crypto; @@ -7,7 +6,6 @@ using Mimir.Worker.Exceptions; using Mimir.Worker.Services; using MongoDB.Driver; -using Nekoyume.Action; using Serilog; namespace Mimir.Worker.ActionHandler; @@ -16,7 +14,7 @@ public class PetStateHandler(IStateService stateService, MongoDbService store) : BaseActionHandler( stateService, store, - "^pet_enhancement[0-9]*$|^combination_equipment[0-9]*$|^rapid_combination[0-9]*$", + "^pet_enhancement[0-9]*$|^combination_equipment[0-9]*$", Log.ForContext() ) { @@ -60,44 +58,6 @@ protected override async Task TryHandleAction( } petId = pid.Value; } - else if ( - System.Text.RegularExpressions.Regex.IsMatch( - actionType, - "^rapid_combination[0-9]*$" - ) - ) - { - avatarAddress = actionValues["avatarAddress"].ToAddress(); - int slotIndex = actionValues["slotIndex"].ToInteger(); - - var slotAddress = avatarAddress.Derive( - string.Format( - CultureInfo.InvariantCulture, - Nekoyume.Model.State.CombinationSlotState.DeriveFormat, - slotIndex - ) - ); - - var combinationSlotState = await StateGetter.GetCombinationSlotStateAsync(slotAddress); - - if (combinationSlotState is null) - { - Logger.Error( - "CombinationSlotState is null\navatar: {avatarAddress}, slotIndex: {slotIndex}", - avatarAddress, - slotIndex - ); - - return false; - } - - if (combinationSlotState.PetId is null) - { - return false; - } - - petId = combinationSlotState.PetId.Value; - } else { throw new ArgumentException($"Unknown actionType: {actionType}"); diff --git a/Mimir.Worker/ActionHandler/RapidCombinationHandler.cs b/Mimir.Worker/ActionHandler/RapidCombinationHandler.cs new file mode 100644 index 00000000..0f9269df --- /dev/null +++ b/Mimir.Worker/ActionHandler/RapidCombinationHandler.cs @@ -0,0 +1,109 @@ +using Bencodex.Types; +using Lib9c.Models.States; +using Libplanet.Crypto; +using Mimir.MongoDB; +using Mimir.MongoDB.Bson; +using Mimir.Worker.Services; +using Mimir.Worker.Exceptions; +using MongoDB.Driver; +using Serilog; + +namespace Mimir.Worker.ActionHandler; + +public class RapidCombinationHandler(IStateService stateService, MongoDbService store) + : BaseActionHandler( + stateService, + store, + "^rapid_combination[0-9]*$", + Log.ForContext()) +{ + protected override async Task TryHandleAction( + string actionType, + long processBlockIndex, + IValue? actionPlainValueInternal, + IClientSessionHandle? session = null, + CancellationToken stoppingToken = default) + { + if (actionPlainValueInternal is not Dictionary d) + { + var e = new InvalidTypeOfActionPlainValueInternalException( + [ValueKind.Dictionary], + actionPlainValueInternal?.Kind); + Logger.Fatal( + e, + "Unexpected actionPlainValueInternal type: {ActionPlainValueInternalType}", + actionPlainValueInternal?.Kind); + return false; + } + + var avatarAddress = d.TryGetValue((Text)"a", out var avatarAddressValue) + ? new Address(avatarAddressValue) + : (Address?)null; + if (avatarAddress is null) + { + var e = new InvalidOperationException( + "Avatar address is missing in the actionPlainValueInternal dictionary. \"a\""); + Logger.Fatal(e, "Failed to deserialization"); + return false; + } + + var slotIndexes = d.TryGetValue((Text)"s", out var slotIndexesValue) + ? ((List)slotIndexesValue).Select(e => (int)(Integer)e) + : null; + if (slotIndexes is null) + { + var e = new InvalidOperationException( + "Slot indexes are missing in the actionPlainValueInternal dictionary. \"s\""); + Logger.Fatal(e, "Failed to deserialization"); + return false; + } + + foreach (var slotIndex in slotIndexes) + { + var slotAddress = Nekoyume.Model.State.CombinationSlotState.DeriveAddress(avatarAddress.Value, slotIndex); + CombinationSlotState combinationSlotState; + try + { + combinationSlotState = await StateGetter.GetCombinationSlotStateAsync(slotAddress, stoppingToken); + } + catch (StateNotFoundException e) + { + Logger.Fatal( + e, + "CombinationSlotState is null\navatar: {AvatarAddress}, slotIndex: {SlotIndex}", + avatarAddress, + slotIndex); + return false; + } + + // handle + var doc = new CombinationSlotStateDocument( + slotAddress, + avatarAddress.Value, + slotIndex, + combinationSlotState); + await Store.UpsertStateDataManyAsync( + CollectionNames.GetCollectionName(), + [doc], + session, + stoppingToken); + + // handle pet id + if (combinationSlotState.PetId.HasValue) + { + var petStateAddress = Nekoyume.Model.State.PetState.DeriveAddress( + avatarAddress.Value, + combinationSlotState.PetId.Value); + var petState = await StateGetter.GetPetState(petStateAddress, stoppingToken); + var petStateDoc = new PetStateDocument(petStateAddress, petState); + await Store.UpsertStateDataManyAsync( + CollectionNames.GetCollectionName(), + [petStateDoc], + session, + stoppingToken); + } + } + + return true; + } +} diff --git a/Mimir.Worker/Poller/TxPoller.cs b/Mimir.Worker/Poller/TxPoller.cs index 9cc46b85..313f3fb6 100644 --- a/Mimir.Worker/Poller/TxPoller.cs +++ b/Mimir.Worker/Poller/TxPoller.cs @@ -56,6 +56,7 @@ MongoDbService dbService new ProductsHandler(stateService, dbService), // Avatar Related new CombinationSlotStateHandler(stateService, dbService), + new RapidCombinationHandler(stateService, dbService), new PetStateHandler(stateService, dbService), new RuneSlotStateHandler(stateService, dbService), new StakeHandler(stateService, dbService),