Skip to content

Commit

Permalink
Merge pull request #65 from moreal/fix-index
Browse files Browse the repository at this point in the history
fix(worker): fetch states with specific block index
  • Loading branch information
moreal authored May 17, 2024
2 parents 696b4c8 + e1427fd commit 217d576
Show file tree
Hide file tree
Showing 14 changed files with 194 additions and 82 deletions.
9 changes: 7 additions & 2 deletions Mimir.Worker/Initializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,13 @@ public Initializer(
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
var started = DateTime.UtcNow;
await _tableSheetScrapper.ExecuteAsync(stoppingToken);
await _arenaScrapper.ExecuteAsync(stoppingToken);
var latestBlockIndex = await _stateService.GetLatestIndex();

await _tableSheetScrapper.ExecuteAsync(latestBlockIndex, stoppingToken);
await _arenaScrapper.ExecuteAsync(latestBlockIndex, stoppingToken);

await _store.UpdateLatestBlockIndex(latestBlockIndex);

_logger.LogInformation(
"Finished Initializer background service. Elapsed {TotalElapsedMinutes} minutes",
DateTime.UtcNow.Subtract(started).Minutes);
Expand Down
4 changes: 2 additions & 2 deletions Mimir.Worker/Queries.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ query GetTip {
}
}

query GetState($accountAddress: Address! $address: Address!) {
state(accountAddress: $accountAddress, address: $address)
query GetState($accountAddress: Address! $address: Address!, $index: Long) {
state(accountAddress: $accountAddress, address: $address, index: $index)
}

query GetBattleArenaTransactions($blockIndex: Long!) {
Expand Down
9 changes: 3 additions & 6 deletions Mimir.Worker/Scrapper/ArenaScrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,10 @@ public class ArenaScrapper(ILogger<ArenaScrapper> logger, IStateService service,
private readonly IStateService _stateService = service;
private readonly MongoDbStore _store = store;

public async Task ExecuteAsync(CancellationToken cancellationToken)
public async Task ExecuteAsync(long blockIndex, CancellationToken cancellationToken)
{
var latestBlockIndex = await service.GetLatestIndex();
var stateGetter = _stateService.At();
var roundData = await stateGetter.GetArenaRoundData(latestBlockIndex);
var stateGetter = _stateService.At(blockIndex);
var roundData = await stateGetter.GetArenaRoundData(blockIndex);
var arenaParticipants = await stateGetter.GetArenaParticipantsState(roundData.ChampionshipId, roundData.Round);

var buffer = new List<(Address AvatarAddress, ArenaData Arena, AvatarData Avatar)>();
Expand All @@ -31,8 +30,6 @@ async Task FlushBufferAsync()

buffer.Clear();
}

await _store.UpdateLatestBlockIndex(latestBlockIndex);

foreach (var avatarAddress in arenaParticipants.AvatarAddresses)
{
Expand Down
26 changes: 14 additions & 12 deletions Mimir.Worker/Scrapper/StateGetter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,19 @@ public class StateGetter
{
private readonly ILogger<StateGetter> _logger;
private readonly IStateService _service;
private readonly long? _index;

public StateGetter(IStateService service)
public StateGetter(IStateService service, long? index=null)
{
_logger = LoggerFactory.Create(builder => builder.AddConsole()).CreateLogger<StateGetter>();
_service = service;
_index = index;
}

public async Task<T> GetSheet<T>()
where T : ISheet, new()
{
var sheetState = await _service.GetState(Addresses.TableSheet.Derive(typeof(T).Name));
var sheetState = await _service.GetState(Addresses.TableSheet.Derive(typeof(T).Name), _index);
if (sheetState is not Text sheetValue)
{
throw new ArgumentException(nameof(T));
Expand All @@ -41,7 +43,7 @@ public async Task<ArenaParticipants> GetArenaParticipantsState(int championshipI
{
var arenaParticipantsAddress =
ArenaParticipants.DeriveAddress(championshipId, roundId);
var state = await _service.GetState(arenaParticipantsAddress);
var state = await _service.GetState(arenaParticipantsAddress, _index);
return state switch
{
List list => new ArenaParticipants(list),
Expand All @@ -53,7 +55,7 @@ public async Task<ArenaScore> GetArenaScoreState(Address avatarAddress, int cham
{
var arenaScoreAddress =
ArenaScore.DeriveAddress(avatarAddress, championshipId, roundId);
var state = await _service.GetState(arenaScoreAddress);
var state = await _service.GetState(arenaScoreAddress, _index);
return state switch
{
List list => new ArenaScore(list),
Expand All @@ -65,7 +67,7 @@ public async Task<ArenaInformation> GetArenaInfoState(Address avatarAddress, int
{
var arenaInfoAddress =
ArenaInformation.DeriveAddress(avatarAddress, championshipId, roundId);
var state = await _service.GetState(arenaInfoAddress);
var state = await _service.GetState(arenaInfoAddress, _index);
return state switch
{
List list => new ArenaInformation(list),
Expand Down Expand Up @@ -129,7 +131,7 @@ public async Task<Inventory> GetInventoryState(Address avatarAddress)
public async Task<ItemSlotState> GetItemSlotState(Address avatarAddress)
{
var state = await _service.GetState(
ItemSlotState.DeriveAddress(avatarAddress, BattleType.Arena));
ItemSlotState.DeriveAddress(avatarAddress, BattleType.Arena), _index);
return state switch
{
List list => new ItemSlotState(list),
Expand All @@ -141,7 +143,7 @@ public async Task<ItemSlotState> GetItemSlotState(Address avatarAddress)
public async Task<List<RuneState>> GetRuneStates(Address avatarAddress)
{
var state = await _service.GetState(
RuneSlotState.DeriveAddress(avatarAddress, BattleType.Arena));
RuneSlotState.DeriveAddress(avatarAddress, BattleType.Arena), _index);
var runeSlotState = state switch
{
List list => new RuneSlotState(list),
Expand All @@ -152,7 +154,7 @@ public async Task<List<RuneState>> GetRuneStates(Address avatarAddress)
var runes = new List<RuneState>();
foreach (var runeStateAddress in runeSlotState.GetEquippedRuneSlotInfos().Select(info => RuneState.DeriveAddress(avatarAddress, info.RuneId)))
{
if (await _service.GetState(runeStateAddress) is List list)
if (await _service.GetState(runeStateAddress, _index) is List list)
{
runes.Add(new RuneState(list));
}
Expand All @@ -163,22 +165,22 @@ public async Task<List<RuneState>> GetRuneStates(Address avatarAddress)

public async Task<IValue?> GetStateWithLegacyAccount(Address address, Address accountAddress)
{
var state = await _service.GetState(address, accountAddress);
var state = await _service.GetState(address, accountAddress, _index);

if (state == null)
{
state = await _service.GetState(address);
state = await _service.GetState(address, _index);
}
return state;
}

public async Task<IValue?> GetAvatarStateWithLegacyAccount(Address avatarAddress, Address accountAddress, Address legacyAddress)
{
var state = await _service.GetState(avatarAddress, accountAddress);
var state = await _service.GetState(avatarAddress, accountAddress, _index);

if (state == null)
{
state = await _service.GetState(legacyAddress);
state = await _service.GetState(legacyAddress, _index);
}
return state;
}
Expand Down
7 changes: 3 additions & 4 deletions Mimir.Worker/Scrapper/TableSheetScrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,9 @@ MongoDbStore store
private readonly IStateService _stateService = service;
private readonly MongoDbStore _store = store;

public async Task ExecuteAsync(CancellationToken cancellationToken)
public async Task ExecuteAsync(long blockIndex, CancellationToken cancellationToken)
{
var latestBlockIndex = await service.GetLatestIndex();
var stateGetter = _stateService.At();
var stateGetter = _stateService.At(blockIndex);

var sheetTypes = typeof(ISheet)
.Assembly.GetTypes()
Expand All @@ -49,7 +48,7 @@ type.Namespace is { } @namespace
}

var sheetAddress = Addresses.TableSheet.Derive(sheetType.Name);
var sheetState = await _stateService.GetState(sheetAddress);
var sheetState = await _stateService.GetState(sheetAddress, blockIndex);
if (sheetState is not Text sheetValue)
{
throw new ArgumentException(nameof(sheetType));
Expand Down
16 changes: 8 additions & 8 deletions Mimir.Worker/Services/HeadlessStateService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,24 @@ public class HeadlessStateService(IHeadlessGQLClient client) : IStateService

public long TipIndex => TipInfo.Item1;

public Task<IValue?[]> GetStates(Address[] addresses)
public Task<IValue?[]> GetStates(Address[] addresses, long? index)
{
return Task.WhenAll(addresses.Select(GetState));
return Task.WhenAll(addresses.Select(addr => GetState(addr, index)));
}

public Task<IValue?[]> GetStates(Address[] addresses, Address accountAddress)
public Task<IValue?[]> GetStates(Address[] addresses, Address accountAddress, long? index)
{
return Task.WhenAll(addresses.Select(addr => GetState(addr, accountAddress)));
return Task.WhenAll(addresses.Select(addr => GetState(addr, accountAddress, index)));
}

public async Task<IValue?> GetState(Address address)
public async Task<IValue?> GetState(Address address, long? index)
{
return await GetState(address, ReservedAddresses.LegacyAccount);
return await GetState(address, ReservedAddresses.LegacyAccount, index);
}

public async Task<IValue?> GetState(Address address, Address accountAddress)
public async Task<IValue?> GetState(Address address, Address accountAddress, long? index)
{
var result = await client.GetState.ExecuteAsync(accountAddress.ToString(), address.ToString());
var result = await client.GetState.ExecuteAsync(accountAddress.ToString(), address.ToString(), index);
result.EnsureNoErrors();

if (result.Data?.State is null)
Expand Down
8 changes: 4 additions & 4 deletions Mimir.Worker/Services/IStateService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ namespace Mimir.Worker.Services;
public interface IStateService
{
Task<int> GetLatestIndex();
Task<IValue?> GetState(Address address);
Task<IValue?> GetState(Address address, Address accountAddress);
Task<IValue?[]> GetStates(Address[] addresses);
Task<IValue?[]> GetStates(Address[] addresses, Address accountAddress);
Task<IValue?> GetState(Address address, long? index);
Task<IValue?> GetState(Address address, Address accountAddress, long? index);
Task<IValue?[]> GetStates(Address[] addresses, long? index);
Task<IValue?[]> GetStates(Address[] addresses, Address accountAddress, long? index);
}
4 changes: 2 additions & 2 deletions Mimir.Worker/Services/StateServiceExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ namespace Mimir.Worker.Services;

public static class StateServiceExtensions
{
public static StateGetter At(this IStateService service)
public static StateGetter At(this IStateService service, long index)
{
return new StateGetter(service);
return new StateGetter(service, index);
}
}
72 changes: 63 additions & 9 deletions Mimir.Worker/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,17 @@ type StandaloneQuery {
stateQuery(
# Offset block hash for query.
hash: ByteString

# Offset block index for query.
index: Long
): StateQuery!
state(
# The hash of the block used to fetch state from chain.
hash: ByteString

# The index of the block used to fetch state from chain.
index: Long

# The address of account to fetch from the chain.
accountAddress: Address!

Expand All @@ -23,7 +29,7 @@ type StandaloneQuery {
blockHash: ByteString!
recipient: Address
): [TransferNCGHistoryType!]!
keyWorker: KeyWorkerType
keyStore: KeyStoreType
@deprecated(
reason: "Use `planet key` command instead. https://www.npmjs.com/package/@planetarium/cli"
)
Expand Down Expand Up @@ -1141,7 +1147,7 @@ type TransferNCGHistoryType {
memo: String
}

type KeyWorkerType {
type KeyStoreType {
protectedPrivateKeys: [ProtectedPrivateKeyType!]!
decryptedPrivateKey(address: Address!, passphrase: String!): ByteString!

Expand Down Expand Up @@ -1248,14 +1254,24 @@ type ExplorerQuery {
stateQuery: LibplanetStateQuery
nodeState: NodeState!
helperQuery: HelperQuery
rawStateQuery: RawStateQuery
}

type BlockQuery {
blocks(
desc: Boolean = false
offset: Int = 0
# Whether to query blocks in descending order or not.
desc: Boolean! = false

# The offset of the first queried block.
offset: Int! = 0

# The maximum number of blocks to return. This limits the offset index range to query, not the result, i.e. excluded blocks due to a block being empty or not matching the miner (if specified in other arguments) are still counted.
limit: Int
excludeEmptyTxs: Boolean = false

# Whether to include empty blocks with no transactions or not. Default is set to false, i.e. to return empty blocks.
excludeEmptyTxs: Boolean! = false

# If not null, returns blocks only by mined by the address given. Default is set to null.
miner: Address
): [Block!]!
block(hash: ID, index: ID): Block
Expand Down Expand Up @@ -1507,6 +1523,9 @@ type WorldState {
# The legacy flag of the world state.
legacy: Boolean!

# The version of the bakcing data model.
version: Int!

# Gets the account associated with given address.
account(
# The address of an account to retrieve.
Expand Down Expand Up @@ -1598,8 +1617,8 @@ type Validator {

type NodeState {
preloaded: Boolean!
peers: [BoundPeer!]
validators: [BoundPeer!]
peers: [BoundPeer!]!
validators: [BoundPeer!]!
}

type BoundPeer {
Expand All @@ -1626,6 +1645,33 @@ type HelperQuery {
# The byte array in hex representation to decode.
hex: String!
): IValue!

# Converts string to key hex representation
keyHex(
# The string value to convert to key hex.
value: String!
): KeyBytes!
}

scalar KeyBytes

type RawStateQuery {
# Retrieves trie from given state root hash.
trie(stateRootHash: HashDigest_SHA256): Trie!
}

type Trie {
# Gets the value stored at given key.
value(
# The key to search.
key: KeyBytes!
): IValue

# Gets the values stored at given multiple keys.
values(
# The list of keys to search.
keys: [KeyBytes!]!
): IValue
}

type ValidationQuery {
Expand Down Expand Up @@ -2119,6 +2165,10 @@ type ActionQuery {
# Memo to attach to this action.
memo: String
): ByteString!
retrieveAvatarAssets(
# Avatar address to retrieve assets
avatarAddress: Address!
): ByteString!

# Query to craft/enhance items/foods
craftQuery: CraftQuery!
Expand Down Expand Up @@ -2522,6 +2572,10 @@ type ActionTxQuery {
# Memo to attach to this action.
memo: String
): ByteString!
retrieveAvatarAssets(
# Avatar address to retrieve assets
avatarAddress: Address!
): ByteString!

# Query to craft/enhance items/foods
craftQuery: CraftQuery!
Expand Down Expand Up @@ -2572,7 +2626,7 @@ type AddressQuery {
}

type StandaloneMutation {
keyWorker: KeyWorkerMutation
keyStore: KeyStoreMutation
@deprecated(
reason: "Use `planet key` command instead. https://www.npmjs.com/package/@planetarium/cli"
)
Expand Down Expand Up @@ -2622,7 +2676,7 @@ type StandaloneMutation {
): TxId!
}

type KeyWorkerMutation {
type KeyStoreMutation {
createPrivateKey(passphrase: String!, privateKey: ByteString): PrivateKeyType!
revokePrivateKey(address: Address!): ProtectedPrivateKeyType!
}
Expand Down
Loading

0 comments on commit 217d576

Please sign in to comment.