Repository navigation
Fix: 4 issues (#1721, #1722, #1723, #1725) - #1846
Merged
yahia008 merged 2 commits intoOct 19, 2026
Merged
Conversation
Co-authored-by: Simple Agent <agent@simple.dev>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #1721
Closes #1722
Closes #1723
Closes #1725
Issues
#1721 Frontend: match status polling uses
setIntervaland never clears it on unmount#1722 Test:
set_minimum_stake/set_maximum_stakeenforce bounds oncreate_match#1723 Performance: event indexer rebuilds the full match state from events on every
/matches/:idrequest#1725 Performance: oracle service pollers do not batch active-match queries, causing N RPC calls per cycle
Summary
The four issues are independent and can be implemented in parallel. For #1721, the existing hook already has a cleanup in the visible portion; verify the full file and ensure the mounted-ref guard and interval cleanup are both correct, then add the unmount tests. For #1722, reuse the existing
setup()fixture and admin setters; assert exactError::InvalidAmountvariants. For #1723, the materialized table must be populated by the ingestion path, not lazily on read, and the read path must not fall back to event replay; keep the existing API response shape and cache invalidation. For #1725, the default trait method keeps backward compatibility for any other providers; batch sizes should respect the existing rate limiter and concurrency semaphore, and rate-limit responses must not be retried in a tight loop.Changes
setIntervalis always cleared on unmount. Ensure theuseEffectthat sets up polling returns a cleanup function that callsclearInterval(intervalRef.current)and nulls the ref, and that the mounted ref is set to false on unmount so in-flightfetchMatchpromises cannot callsetStateafter unmount. Also make sure a terminal-state poll clears the interval exactly once and does not leave a dangling timer. (frontend/src/hooks/useMatchStatus.ts)getMatchFncalls when timers are advanced, and (2) resolving a pendinggetMatchFnpromise after unmount does not updateresult.current(loading/match/error remain at their pre-unmount values). Use fake timers andrenderHook/unmountas in the existing cleanup tests. (frontend/src/hooks/useMatchStatus.test.ts)create_match. Using the admin settersset_minimum_stakeandset_maximum_stake, configure a known min/max, then assert: a stake below the minimum returnsErr(Ok(Error::InvalidAmount)); a stake above the maximum returnsErr(Ok(Error::InvalidAmount)); and stakes exactly equal to the minimum and exactly equal to the maximum are accepted (return a match id). Cover the case where only one bound is configured and the case where both are configured. (contracts/escrow/src/tests/match_validation.rs)matchesmaterialized-state table to the indexer schema (created in the same schema-initialization path as the existingevents/leader_statetables), with columns for match id (primary key), player1, player2, status, winner, stake_amount, token, game_id, platform, created_ledger, completed_ledger, and updated_at. Add an upsert method (e.g.upsert_match_state) that writes the latest known state for a match, and changebuild_match_info/get_match_by_idto read the materialized row instead of replaying all events. Keep the event log for history but stop using it to reconstruct current state on the read path. (services/event-indexer/src/db.rs)MatchStateRow(or similar) model representing a row of the newmatchesmaterialized table, with fields matching the table columns, so the db layer can map rows toMatchInfowithout replaying events. (services/event-indexer/src/models.rs)matchesrow for that match is updated incrementally (upsert with the event's status/winner/player/stake/token/game_id/platform/ledger fields). This keeps the table current without a full replay. Ensure the update happens in the same transaction or immediately after the idempotent insert so replays remain safe. (services/event-indexer/src/main.rs)GET /matches/:idhandler to serve the match from the materializedmatchestable via the new db method instead of reconstructing state from events. Preserve the existing 404/500 response shapes and cache invalidation behavior. (services/event-indexer/src/api.rs)GET /matches/:idreads from the materializedmatchestable: insert a match state row directly, request the endpoint, and assert the returnedMatchInforeflects the materialized row (and that it does not depend on replaying events). Also keep the existing not-found and validation tests passing. (services/event-indexer/tests/get_match_endpoint_tests.rs)GameProvidertrait (e.g.fetch_results_batch(&self, game_ids: &[String]) -> Vec<(String, Result<Winner, ProviderError>)>with a default implementation that loops overfetch_result, so existing providers keep working). UpdateProviderRegistryto expose a batch fetch that groups by provider and preserves per-game error reporting. (oracle-service/src/oracle/provider.rs)fetch_results_batchfor the Lichess client using the batch game-status endpoint (e.g./api/games/status?ids=...or the export endpoint with multiple ids), chunking game IDs into bounded batches, acquiring one rate-limit token and one concurrency permit per batch request, and mapping per-game results/errors back to the input IDs. On a 429/rate-limit response, surface a rate-limited error so the poller can apply back-pressure. (oracle-service/src/oracle/lichess_client.rs)fetch_results_batchfor the Chess.com client using its batch game-status endpoint where available, chunking IDs into bounded batches, acquiring one rate-limit token and one concurrency permit per batch request, and mapping per-game results/errors back to the input IDs. On a 429/rate-limit response, surface a rate-limited error so the poller can apply back-pressure. (oracle-service/src/oracle/chess_com_client.rs)