Repository navigation
perf(frontend): add stable pagination and snapshot behavior to transfer history - #297
Open
woahwhattheheck wants to merge 23 commits into
Open
woahwhattheheck wants to merge 23 commits into
woahwhattheheck wants to merge 23 commits into
Conversation
Replace offset paging with a filter-scoped snapshot so concurrent inserts cannot duplicate or omit rows mid-scroll. Cursors carry a stable (createdAt, id) tie-breaker; filter changes mint a new snapshot; expired cursors recover by rebuilding from the live list. Closes RemitFlow#278
Keep snapshot membership stable while looking up current row fields in the complete live transfer list. A pending row that settles during refresh now shows Completed without disappearing from the snapshot. Add resolver and application-refresh regressions. Snapshot, filter and selection checks: 23 passed. Production build and critical audit gate passed. Full suite has 459 passes and 12 pre-existing failures; those same 12 failure names reproduce on untouched d02dc97. The four modified files pass Prettier; 10 unrelated baseline files still fail the repository-wide formatting gate.
Use the resolved snapshot count for the empty-state branch and selection totals. Settling the last pending match no longer hides retained rows, and concurrent inserts do not inflate the selected count. Preserve the resolver, cursor behavior and prior live-field refresh repair. Extend the existing App snapshot integration file with all-settled and concurrent-insert regressions, retaining the three prior cases. A dependency-free observation of the exact exported resolver and verbatim page expressions improves from 5/9 to 9/9, with four corrected results and five unchanged controls under Node 24.19.0. This observation does not mount React. The five-case maintained file, full JSX parse, formatting, lint, full suite, build, audit, browser screenshots and Lighthouse remain unrun for this continuation. Preserve historical parent validation and its recorded baseline failures; no dependency scan or install.
Append an invocation-local generation to automatically minted snapshot IDs. Equal-time/equal-size replacements can no longer accept old cursors or be dropped by the existing page identity comparison. Existing snapshots, caller-supplied IDs, filters, ordering and TTL are unchanged. Validation: maintained test/unit/transfer-snapshot.test.js passed 11/11 under Node v22.23.3, using the locked package install. No application build, full suite or browser interaction was run. Run: https://github.com/woahwhattheheck/RemitFlow-Frontend/actions/runs/37192074014
Bind selection to the frozen generation that the user selected. When TTL or cursor recovery persists a replacement snapshot, clear both explicit IDs and select-all. Otherwise a newly inserted transfer silently becomes selected and removed rows remain counted. Same-generation refreshes, live status updates, pagination, filter resets, and the existing cursor-generation fix remain unchanged. Actual mounted App regression on exact parent b8c2226: both new cases failed. The first observed the newcomer's checkbox checked after expiry; the second observed 1 transfer selected after its row disappeared. The baseline used a name filter for only these two new cases (five existing cases were not selected). After correction the complete maintained test/integration/transfers-snapshot-pagination.test.jsx passed 7/7, zero failed or skipped, Vitest 4.1.10 / Node 24.19.0 / React and jsdom. Duration 9.19s, tests 6.48s. Existing frozen membership, filter reset, settled-row refresh, retained selection, and concurrent-insert cases all ran alongside both regressions. This is the real mounted App and repository localStorage transfer service, not a live payment or wallet execution. Reproduction from repository root with its normal writable cache: node node_modules/vitest/vitest.mjs run test/integration/transfers-snapshot-pagination.test.jsx --maxWorkers=1 --fileParallelism=false The cloud run reused installed dependencies only after package.json, package-lock.json, Vite config, and test/setup.js matched the retained runtime. It imported the original Vite config with only cacheDir redirected to task scratch because the root filesystem was full; TMPDIR was similarly redirected. No install, source mocks, fake timers, unrelated test edits, full-suite/build, Lighthouse or hosted-CI pass is claimed. Only Date.now is controlled in the two expiry cases. Both changed files were formatted with existing Prettier 3.9.6. Executed blobs: Transfers.jsx 38249e1; maintained regression fbb7f2c. Original PR297, issue278, branch and contribution custody are retained. Attribution: GPT-6 Astra Pro / Relay-17 GrantFox delivery / ChatGPT cloud harness15a9c3b91fc7.
Continue original PR297 after snapshot selection recovery aa146d6. Four maintained test fixtures reuse the already-executed RF296 corrections only after all original fixture blobs match; confirmation/result navigation, exact amounts, offline blocking, retry/no-duplicate assertions, and canonical decimal expectations are preserved. Derive the one valid-amount/null-price explanation from this branch's SendMoney source. Format only the nine files flagged by existing Prettier3.9.6. No dependency/config changes, test removals, skips, timeout changes, or snapshot changes. One complete package selection on this exact source tree a4af225: 477 passed, 0 failed, 0 pending/todo across49 files. Node24.19.0 / Vitest4.1.10; 2026-10-04 11:54:56.918428Z to11:55:54.031767Z,57.113s process/56.57s Vitest. All344 tracked files verified before/after. Existing Prettier check passed. npm run build passed in2.309s, Vite5.4.21 reported1.55s/119modules; same344 files unchanged. The unchanged package625d0f3895fcc7afbfcfa131713249f5cd65dcd6 and lock70d29c1865dac7ce76ba7d4e6ca5ee454be54aae reuse the2026-10-04 10:00:59Z critical-audit receipt: exit0,0critical,20high/12moderate/2low. This is dated evidence for identical dependencies, not a newly refreshed advisory scan. Shared installed dependencies were reused only after package/lock/Vite/setup matches; cloud TMPDIR/cacheDir were task-local because root was full. No live provider, hosted CI, Lighthouse performance, merge, reward or settlement claim. Existing source/contribution custody preserved. Durable raw gate evidence is added by the immediate documentation child before one non-force original-branch update.
Record exact source157ff7bffe98c96ad48b39c844ff51a0a070679a/treea4af225:477 passed,0 failed,0 skipped across49 files; existing Prettier and production build passed. Add the reviewable report, receipt and60,612-byte raw evidence ZIP (SHA256838969807560e6854a77c084694bf730e13ecd792046d2ad9d82860a358ec450). All344 executed application/test blobs remain unchanged. Reuse Relay-17 root's newer11:56:36Z critical-audit execution only after identical package/lock bytes were verified in both checkouts.0critical,20high/12moderate/2low; no duplicate request and no noncritical remediation claim. Original donor run receipt and raw audit JSON retained. This source-visible update supersedes the earlier10:00:59Z audit note while keeping its dated statement accurate. This documentation child and its tested source parent are published together through one non-force original-branch update. No hosted CI/Lighthouse, live transfer, sponsor acceptance, award or settlement claim. Attribution: GPT-6 Astra Pro / Relay-17 GrantFox delivery / ChatGPT cloud harness15a9c3b91fc7.
Remove the summary receipt's optional authorship field. Preserve all source, runtime, donor, result and archive data.
Preserve full snapshot membership, native sparse-entry placement, stable equal-key order and locale-aware ID ties while avoiding timestamp parsing inside the comparator. Keep the existing pagination and recovery paths unchanged. Add two focused regressions for ordering compatibility and one parse per populated row.
Preserve the concurrent receipt cleanup and the exact source/test bytes exercised in run 37201593676. Add source-bound constructor measurements and reproduction instructions. No execution workflow or dependency changes.
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 #278
Summary
Transfer history uses a filter-scoped snapshot so concurrent inserts cannot duplicate or omit rows while paging. This continuation fixes recovery and selection behavior, prepares sort keys once, and repairs existing CI fixtures.
Behavior and compatibility
Snapshot performance
The sorter prepares timestamp/string-ID keys once per populated row and returns the original row references. It preserves locale ties, invalid-date fallback and undefined/sparse placement.
Measured calls to the actual snapshot constructor include record copying: Node 22.16.0, two warmups and five alternating paired samples per workload, with complete output equality:
Separate untimed counting measured 3,058,470 → 100,000 timestamp parses for the large shuffled case. The tradeoff is one temporary key record per populated row; peak memory was not measured. Storage parsing, network/provider work and React rendering are excluded.
Benchmark, raw samples, exact source pins and focused execution.
Validation and current status
Current head: 1ee074a. Subsequent lookup, across-page selection, and inactive-date-filter changes retain their source-specific evidence below.
Aggregate commands, receipt and raw evidence. Hosted CI and Lighthouse require approval; maintainer acceptance remains pending.
Page lookup continuations
At 3bb8747d, page lookups retain only visible snapshot IDs rather than allocating a full-history Map and temporary pairs for each page. The lookup preserves the last duplicate-ID winner, exact live references and captured-record fallback for missing rows, with no persistent cache. Direct production-module measurement on Node 22.16/Linux: 100,000 rows with the default five-row page measured 14.269 → 1.606 ms median (8.89x); lookup cardinality fell from 100,000 to 5. Complete outputs and references matched across bounded mutation, insertion, duplicate, expiry and scope observations. Source pins, all four workloads, raw samples and runnable measurement.
Subsequent source afa3b0ef retains the bounded page map and avoids unnecessary live-history traversal. Ordinary arrays are scanned backward so the first match preserves the last-duplicate-wins policy; scanning stops after every visible ID is resolved. Empty pages read no live records. Missing IDs retain their snapshot fallback after a full scan. Sets, generators and custom array iterators keep their forward-only behavior.
Three focused assertion groups passed against the complete production module, and all six benchmark workload outputs and record references matched the preceding source. On Node 22.16, the 100,000-row ascending-input newest page measured 2.793942 → 0.007302 ms, and an empty filtered snapshot 1.590464 → 0.002271 ms. Full-scan controls were essentially unchanged: descending first page 2.754172 → 2.726743 ms; ascending last page 2.798958 → 2.804947 ms. Nine alternating pairs, twenty calls per sample. Source pins, reproduction program, raw samples and limits.
These results depend on input position and measure only the helper. Prior benchmark ratios must not be multiplied; no browser, provider or whole-application speedup is claimed. No Vitest suite, build or workflow was rerun for either lookup continuation; earlier validation remains source-specific. Maintainer acceptance remains pending.
Across-page deselection
Across-page deselection now converts the frozen membership to explicit IDs before removing a row or page, so other-page selections survive. The maintained selection integration file passes all five cases with no skipped cases on Node 24.21.0 and unchanged locked dependencies at production source 6ed4086f; both new cases fail against the preceding component. Scoped formatting and source-identity checks pass. Execution and limits.
Inactive date filter
At production source 9f1debe8, the All time filter defers its default Date allocation until a nonzero date range needs it. Supplied clocks, inclusive cutoffs, invalid dates and active ranges keep their behavior. Previous selection and pagination changes remain.
A native Node 22.16.0/Linux measurement of Array.filter calling the complete production helper over 100,000 records used three warmups and nine alternating paired samples. The All time median measured 12.115259 → 4.508355 ms (62.79% less time), with identical membership, order and object references; separate untimed clock allocations fell from 100,000 to zero. The active 30-day control measured 62.660949 → 60.724011 ms with 100,000 allocations in both implementations; that small difference is not treated as a material active-filter gain. Rendering, API and storage work are excluded.
Native run 37206173166 passes all eight unchanged transfers-filter integration cases at pinned source 9f1debe, including no-filter display, date presets and URL restoration. The original lock is installed; scoped formatting and clean-worktree checks pass. No test file or dependency was added. Source pins, raw samples, reproduction and limits.
These separate source-bound results are not combined into a current-head whole-suite total or a cumulative performance multiplier. No full build, deployed throughput, acceptance or payout is asserted for these continuations.