Skip to content

Commit

Permalink
feat: separate migration / deletion
Browse files Browse the repository at this point in the history
  • Loading branch information
limebell committed Mar 6, 2024
1 parent 57cb40c commit cdc7f40
Show file tree
Hide file tree
Showing 4 changed files with 248 additions and 23 deletions.
6 changes: 0 additions & 6 deletions .Lib9c.Tests/Action/MigrateAgentAvatarTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -162,12 +162,6 @@ public void MigrateAgentAvatar(int legacyAvatarVersion, bool alreadyMigrated)
}
);

Assert.Null(nextState.GetLegacyState(agentAddress));
Assert.Null(nextState.GetLegacyState(avatarAddress));
Assert.Null(nextState.GetLegacyState(inventoryAddress));
Assert.Null(nextState.GetLegacyState(worldInformationAddress));
Assert.Null(nextState.GetLegacyState(questListAddress));

Assert.NotNull(nextState.GetAccount(Addresses.Agent).GetState(agentAddress));
Assert.NotNull(nextState.GetAccount(Addresses.Avatar).GetState(avatarAddress));
Assert.NotNull(nextState.GetAccount(Addresses.Inventory).GetState(avatarAddress));
Expand Down
145 changes: 145 additions & 0 deletions .Lib9c.Tests/Action/RemoveLegacyAgentAvatarTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
namespace Lib9c.Tests.Action
{
using System;
using System.Collections.Generic;
using System.Globalization;
using Bencodex.Types;
using Libplanet.Action;
using Libplanet.Action.State;
using Libplanet.Crypto;
using Libplanet.Types.Assets;
using Nekoyume;
using Nekoyume.Action;
using Nekoyume.Action.Loader;
using Nekoyume.Model.State;
using Nekoyume.Module;
using Nekoyume.TableData;
using Xunit;
using static Lib9c.SerializeKeys;

public class RemoveLegacyAgentAvatarTest
{
private readonly TableSheets _tableSheets;

public RemoveLegacyAgentAvatarTest()
{
var sheets = TableSheetsImporter.ImportSheets();
sheets[nameof(CharacterSheet)] = string.Join(
Environment.NewLine,
"id,_name,size_type,elemental_type,hp,atk,def,cri,hit,spd,lv_hp,lv_atk,lv_def,lv_cri,lv_hit,lv_spd,attack_range,run_speed",
"100010,전사,S,0,300,20,10,10,90,70,12,0.8,0.4,0,3.6,2.8,2,3");
_tableSheets = new TableSheets(sheets);
}

[Theory]
[InlineData(1)]
[InlineData(2)]
public void RemoveLegacyAgentAvatar(int legacyAvatarVersion)
{
var avatarIndex = 1;
var agentAddress = new PrivateKey().Address;
var agentState = new AgentState(agentAddress);
var avatarAddress = agentAddress.Derive(string.Format(CultureInfo.InvariantCulture, CreateAvatar.DeriveFormat, avatarIndex));
agentState.avatarAddresses.Add(avatarIndex, avatarAddress);

var inventoryAddress = avatarAddress.Derive(LegacyInventoryKey);
var questListAddress = avatarAddress.Derive(LegacyQuestListKey);
var worldInformationAddress = avatarAddress.Derive(LegacyWorldInformationKey);

var weekly = new WeeklyArenaState(0);
var gameConfigState = new GameConfigState();
gameConfigState.Set(_tableSheets.GameConfigSheet);
var currency = Currency.Legacy("NCG", 2, null);

var avatarState = new AvatarState(
avatarAddress,
agentAddress,
456,
_tableSheets.GetAvatarSheets(),
gameConfigState,
default);

MockWorldState mock = new MockWorldState()
.SetState(
ReservedAddresses.LegacyAccount,
GoldCurrencyState.Address,
new GoldCurrencyState(currency, 0).Serialize())
.SetState(
ReservedAddresses.LegacyAccount,
weekly.address,
weekly.Serialize())
.SetState(
ReservedAddresses.LegacyAccount,
Addresses.GoldDistribution,
new List())
.SetState(
ReservedAddresses.LegacyAccount,
gameConfigState.address,
gameConfigState.Serialize());

switch (legacyAvatarVersion)
{
case 1:
mock = mock
.SetState(
ReservedAddresses.LegacyAccount,
agentAddress,
agentState.SerializeList())
.SetState(
ReservedAddresses.LegacyAccount,
avatarAddress,
MigrationAvatarState.LegacySerializeV1(avatarState));
break;
case 2:
mock = mock
.SetState(
ReservedAddresses.LegacyAccount,
agentAddress,
agentState.SerializeList())
.SetState(
ReservedAddresses.LegacyAccount,
avatarAddress,
MigrationAvatarState.LegacySerializeV1(avatarState))
.SetState(
ReservedAddresses.LegacyAccount,
inventoryAddress,
avatarState.inventory.Serialize())
.SetState(
ReservedAddresses.LegacyAccount,
worldInformationAddress,
avatarState.questList.Serialize())
.SetState(
ReservedAddresses.LegacyAccount,
questListAddress,
avatarState.questList.Serialize());
break;
default:
throw new ArgumentException($"Invalid legacy avatar version: {legacyAvatarVersion}");
}

IAction action = new RemoveLegacyAgentAvatar
{
AgentAddresses = new List<Address> { agentAddress },
};

var plainValue = action.PlainValue;
var actionLoader = new NCActionLoader();
action = actionLoader.LoadAction(123, plainValue);

var states = new World(mock);
IWorld nextState = action.Execute(
new ActionContext()
{
PreviousState = states,
Miner = default,
}
);

Assert.Null(nextState.GetLegacyState(agentAddress));
Assert.Null(nextState.GetLegacyState(avatarAddress));
Assert.Null(nextState.GetLegacyState(inventoryAddress));
Assert.Null(nextState.GetLegacyState(worldInformationAddress));
Assert.Null(nextState.GetLegacyState(questListAddress));
}
}
}
26 changes: 9 additions & 17 deletions Lib9c/Action/MigrateAgentAvatar.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
using Libplanet.Action;
using Libplanet.Action.State;
using Libplanet.Crypto;
using Nekoyume.Model.State;
using Nekoyume.Module;
using Serilog;
using static Lib9c.SerializeKeys;
Expand Down Expand Up @@ -43,7 +42,9 @@ public override IWorld Execute(IActionContext context)
context.UseGas(1);
var states = context.PreviousState;
var migrationStarted = DateTimeOffset.UtcNow;
Log.Debug("Migration in block index #{Index} started", context.BlockIndex);
Log.Debug(
"Migrating agent/avatar states in block index #{Index} started",
context.BlockIndex);

const int maxAvatarCount = 3;
var avatarAddresses = Enumerable
Expand All @@ -67,13 +68,10 @@ public override IWorld Execute(IActionContext context)
states = states.SetAgentState(address, agentState);
}

// Delete AgentState in Legacy
Log.Debug("Deleting agent {Address} from legacy account", address);
states = states.SetLegacyState(address, null);
Log.Debug(
"Migrating agent {Address} finished in: {Elapsed}",
"Migrating agent {Address} finished in: {Elapsed} ms",
address,
DateTimeOffset.UtcNow - started);
(DateTimeOffset.UtcNow - started).Milliseconds);
}

foreach (var address in avatarAddresses)
Expand All @@ -90,23 +88,17 @@ public override IWorld Execute(IActionContext context)
states = states.SetAvatarState(address, avatarState);
}

// Delete AvatarState in Legacy
Log.Debug("Deleting avatar {Address} from legacy account", address);
states = states.SetLegacyState(address, null);
states = states.SetLegacyState(address.Derive(LegacyInventoryKey), null);
states = states.SetLegacyState(address.Derive(LegacyQuestListKey), null);
states = states.SetLegacyState(address.Derive(LegacyWorldInformationKey), null);
Log.Debug(
"Migrating avatar {Address} finished in: {Elapsed}",
"Migrating avatar {Address} finished in: {Elapsed} ms",
address,
DateTimeOffset.UtcNow - started);
(DateTimeOffset.UtcNow - started).Milliseconds);
}

Log.Debug(
"Migration of {Count} agents in block index #{Index} finished in: {Elapsed}",
"Migrating {Count} agents in block index #{Index} finished in: {Elapsed} ms",
AgentAddresses.Count,
context.BlockIndex,
DateTimeOffset.UtcNow - migrationStarted);
(DateTimeOffset.UtcNow - migrationStarted).Milliseconds);
return states;
}
}
Expand Down
94 changes: 94 additions & 0 deletions Lib9c/Action/RemoveLegacyAgentAvatar.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Bencodex.Types;
using Libplanet.Action;
using Libplanet.Action.State;
using Libplanet.Crypto;
using Nekoyume.Module;
using Serilog;
using static Lib9c.SerializeKeys;

namespace Nekoyume.Action
{
[ActionType(TypeIdentifier)]
public class RemoveLegacyAgentAvatar : ActionBase
{
public const string TypeIdentifier = "remove_legacy_agent_avatar";

public List<Address> AgentAddresses;

public RemoveLegacyAgentAvatar()
{
}

public override IValue PlainValue => Dictionary.Empty
.Add("type_id", TypeIdentifier)
.Add(
"values",
Dictionary.Empty.Add(
"agent_addresses",
new List(AgentAddresses.Select(address => address.Bencoded))));

public override void LoadPlainValue(IValue plainValue)
{
var asDict = (Dictionary)((Dictionary)plainValue)["values"];
AgentAddresses = ((List)asDict["agent_addresses"]).Select(v => new Address(v)).ToList();
}

public override IWorld Execute(IActionContext context)
{
context.UseGas(1);
var states = context.PreviousState;
var removeStarted = DateTimeOffset.UtcNow;
Log.Debug(
"Removing legacy agent/avatar states in block index #{Index} started",
context.BlockIndex);

const int maxAvatarCount = 3;
var avatarAddresses = Enumerable
.Range(0, AgentAddresses.Count * maxAvatarCount)
.Select(i => AgentAddresses[i / maxAvatarCount]
.Derive(
string.Format(CultureInfo.InvariantCulture, CreateAvatar.DeriveFormat, i % maxAvatarCount)))
.ToList();

foreach (var address in AgentAddresses)
{
// Delete AgentState in Legacy
var started = DateTimeOffset.UtcNow;
Log.Debug("Removing agent {Address} from legacy account", address);
states = states.SetLegacyState(address, null);
Log.Debug(
"Removing agent {Address} finished in: {Elapsed} ms",
address,
(DateTimeOffset.UtcNow - started).Milliseconds);
}

foreach (var address in avatarAddresses)
{
// Delete AvatarState in Legacy
var started = DateTimeOffset.UtcNow;
Log.Debug(
"Removing avatar {Address} and its related states from legacy account",
address);
states = states.SetLegacyState(address, null);
states = states.SetLegacyState(address.Derive(LegacyInventoryKey), null);
states = states.SetLegacyState(address.Derive(LegacyQuestListKey), null);
states = states.SetLegacyState(address.Derive(LegacyWorldInformationKey), null);
Log.Debug(
"Removing avatar {Address} and its related states finished in: {Elapsed} ms",
address,
(DateTimeOffset.UtcNow - started).Milliseconds);
}

Log.Debug(
"Removing {Count} legacy agents in block index #{Index} finished in: {Elapsed} ms",
AgentAddresses.Count,
context.BlockIndex,
(DateTimeOffset.UtcNow - removeStarted).Milliseconds);
return states;
}
}
}

0 comments on commit cdc7f40

Please sign in to comment.