diff --git a/Mimir.Worker/Initializer.cs b/Mimir.Worker/Initializer.cs index 172937f6..05539093 100644 --- a/Mimir.Worker/Initializer.cs +++ b/Mimir.Worker/Initializer.cs @@ -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); diff --git a/Mimir.Worker/Queries.graphql b/Mimir.Worker/Queries.graphql index bdbfb73e..7c389cae 100644 --- a/Mimir.Worker/Queries.graphql +++ b/Mimir.Worker/Queries.graphql @@ -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!) { diff --git a/Mimir.Worker/Scrapper/ArenaScrapper.cs b/Mimir.Worker/Scrapper/ArenaScrapper.cs index ccfa4d99..dd99c33e 100644 --- a/Mimir.Worker/Scrapper/ArenaScrapper.cs +++ b/Mimir.Worker/Scrapper/ArenaScrapper.cs @@ -11,11 +11,10 @@ public class ArenaScrapper(ILogger 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)>(); @@ -31,8 +30,6 @@ async Task FlushBufferAsync() buffer.Clear(); } - - await _store.UpdateLatestBlockIndex(latestBlockIndex); foreach (var avatarAddress in arenaParticipants.AvatarAddresses) { diff --git a/Mimir.Worker/Scrapper/StateGetter.cs b/Mimir.Worker/Scrapper/StateGetter.cs index 7e30ae4a..dd038ffb 100644 --- a/Mimir.Worker/Scrapper/StateGetter.cs +++ b/Mimir.Worker/Scrapper/StateGetter.cs @@ -16,17 +16,19 @@ public class StateGetter { private readonly ILogger _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(); _service = service; + _index = index; } public async Task GetSheet() 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)); @@ -41,7 +43,7 @@ public async Task 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), @@ -53,7 +55,7 @@ public async Task 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), @@ -65,7 +67,7 @@ public async Task 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), @@ -129,7 +131,7 @@ public async Task GetInventoryState(Address avatarAddress) public async Task 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), @@ -141,7 +143,7 @@ public async Task GetItemSlotState(Address avatarAddress) public async Task> 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), @@ -152,7 +154,7 @@ public async Task> GetRuneStates(Address avatarAddress) var runes = new List(); 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)); } @@ -163,22 +165,22 @@ public async Task> GetRuneStates(Address avatarAddress) public async Task 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 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; } diff --git a/Mimir.Worker/Scrapper/TableSheetScrapper.cs b/Mimir.Worker/Scrapper/TableSheetScrapper.cs index 46b376e2..9e357e60 100644 --- a/Mimir.Worker/Scrapper/TableSheetScrapper.cs +++ b/Mimir.Worker/Scrapper/TableSheetScrapper.cs @@ -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() @@ -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)); diff --git a/Mimir.Worker/Services/HeadlessStateService.cs b/Mimir.Worker/Services/HeadlessStateService.cs index 4b1d20dd..7652d179 100644 --- a/Mimir.Worker/Services/HeadlessStateService.cs +++ b/Mimir.Worker/Services/HeadlessStateService.cs @@ -16,24 +16,24 @@ public class HeadlessStateService(IHeadlessGQLClient client) : IStateService public long TipIndex => TipInfo.Item1; - public Task GetStates(Address[] addresses) + public Task GetStates(Address[] addresses, long? index) { - return Task.WhenAll(addresses.Select(GetState)); + return Task.WhenAll(addresses.Select(addr => GetState(addr, index))); } - public Task GetStates(Address[] addresses, Address accountAddress) + public Task 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 GetState(Address address) + public async Task GetState(Address address, long? index) { - return await GetState(address, ReservedAddresses.LegacyAccount); + return await GetState(address, ReservedAddresses.LegacyAccount, index); } - public async Task GetState(Address address, Address accountAddress) + public async Task 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) diff --git a/Mimir.Worker/Services/IStateService.cs b/Mimir.Worker/Services/IStateService.cs index 46c5f78a..f5eb0968 100644 --- a/Mimir.Worker/Services/IStateService.cs +++ b/Mimir.Worker/Services/IStateService.cs @@ -7,8 +7,8 @@ namespace Mimir.Worker.Services; public interface IStateService { Task GetLatestIndex(); - Task GetState(Address address); - Task GetState(Address address, Address accountAddress); - Task GetStates(Address[] addresses); - Task GetStates(Address[] addresses, Address accountAddress); + Task GetState(Address address, long? index); + Task GetState(Address address, Address accountAddress, long? index); + Task GetStates(Address[] addresses, long? index); + Task GetStates(Address[] addresses, Address accountAddress, long? index); } diff --git a/Mimir.Worker/Services/StateServiceExtensions.cs b/Mimir.Worker/Services/StateServiceExtensions.cs index c79ff023..176a93fc 100644 --- a/Mimir.Worker/Services/StateServiceExtensions.cs +++ b/Mimir.Worker/Services/StateServiceExtensions.cs @@ -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); } } diff --git a/Mimir/Queries.graphql b/Mimir/Queries.graphql index 4789f72d..76e78256 100644 --- a/Mimir/Queries.graphql +++ b/Mimir/Queries.graphql @@ -6,6 +6,6 @@ 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) } diff --git a/Mimir/Services/HeadlessStateService.cs b/Mimir/Services/HeadlessStateService.cs index efc48416..04fa81e8 100644 --- a/Mimir/Services/HeadlessStateService.cs +++ b/Mimir/Services/HeadlessStateService.cs @@ -16,24 +16,24 @@ public class HeadlessStateService(IHeadlessGQLClient client) : IStateService public long TipIndex => TipInfo.Item1; - public Task GetStates(Address[] addresses) + public Task GetStates(Address[] addresses, long? index=null) { - return Task.WhenAll(addresses.Select(GetState)); + return Task.WhenAll(addresses.Select(addr => GetState(addr, index))); } - public Task GetStates(Address[] addresses, Address accountAddress) + public Task 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 GetState(Address address) + public async Task GetState(Address address, long? index) { - return await GetState(address, ReservedAddresses.LegacyAccount); + return await GetState(address, ReservedAddresses.LegacyAccount, index); } - public async Task GetState(Address address, Address accountAddress) + public async Task 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) diff --git a/Mimir/Services/IStateService.cs b/Mimir/Services/IStateService.cs index 4ddd0a3f..74544373 100644 --- a/Mimir/Services/IStateService.cs +++ b/Mimir/Services/IStateService.cs @@ -6,8 +6,8 @@ namespace Mimir.Services; public interface IStateService { - Task GetState(Address address); - Task GetState(Address address, Address accountAddress); - Task GetStates(Address[] addresses); - Task GetStates(Address[] addresses, Address accountAddress); + Task GetState(Address address, long? index); + Task GetState(Address address, Address accountAddress, long? index); + Task GetStates(Address[] addresses, long? index); + Task GetStates(Address[] addresses, Address accountAddress, long? index); } diff --git a/Mimir/Util/StateGetter.cs b/Mimir/Util/StateGetter.cs index 8245f2a3..9b5a09e5 100644 --- a/Mimir/Util/StateGetter.cs +++ b/Mimir/Util/StateGetter.cs @@ -13,23 +13,23 @@ namespace Mimir.Util; -public class StateGetter(IStateService stateService) +public class StateGetter(IStateService stateService, long? index=null) { public async Task GetStateAsync(Address address, Address accountAddress) => - await stateService.GetState(address, accountAddress) ?? - await stateService.GetState(address); + await stateService.GetState(address, accountAddress, index) ?? + await stateService.GetState(address, index); public async Task GetStateWithLegacyAccountAsync( Address address, Address accountAddress, Address legacyAddress) => - await stateService.GetState(address, accountAddress) ?? - await stateService.GetState(legacyAddress); + await stateService.GetState(address, accountAddress, index) ?? + await stateService.GetState(legacyAddress, index); public async Task GetSheetAsync() where T : ISheet, new() { - var sheetState = await stateService.GetState(Addresses.GetSheetAddress()); + var sheetState = await stateService.GetState(Addresses.GetSheetAddress(), index); if (sheetState is not Text sheetValue) { throw new ArgumentException(nameof(T)); @@ -44,8 +44,8 @@ await stateService.GetState(address, accountAddress) ?? Address agentAddress, bool withInventory = true) { - var rawState = await stateService.GetState(agentAddress, Addresses.Agent) ?? - await stateService.GetState(agentAddress); + var rawState = await stateService.GetState(agentAddress, Addresses.Agent, index) ?? + await stateService.GetState(agentAddress, index); var agentState = rawState switch { List agentStateList => new AgentState(agentStateList), @@ -124,7 +124,7 @@ await stateService.GetState(address, accountAddress) ?? public async Task GetItemSlotStateAsync(Address avatarAddress) { var state = await stateService.GetState( - ItemSlotState.DeriveAddress(avatarAddress, BattleType.Arena)); + ItemSlotState.DeriveAddress(avatarAddress, BattleType.Arena), index); return state switch { List list => new ItemSlotState(list), @@ -176,7 +176,8 @@ public async Task> GetCollectionStatesAsync var result = new Dictionary(); var values = await stateService.GetStates( addresses.ToArray(), - Addresses.Collection + Addresses.Collection, + index ); for (var i = 0; i < addresses.Count; i++) {