Skip to content

perf(frontend): make transfer search and filtering deterministic at scale - #298

Open
woahwhattheheck wants to merge 14 commits into
RemitFlow:mainfrom
woahwhattheheck:latch/remitflow-281-search-filters
Open

woahwhattheheck wants to merge 14 commits into
RemitFlow:mainfrom
woahwhattheheck:latch/remitflow-281-search-filters

Conversation

@woahwhattheheck

@woahwhattheheck woahwhattheheck commented Sep 24, 2026 •

Copy link
Copy Markdown

Closes #281

Summary

Transfer search keeps actor scope, cancellation and stable capped results. This continuation fixes navigation and validation gaps, improves large-history selection, and closes local CI failures.

Behavior and compatibility

  • Restrict raw rows to the actor before validation. Foreign-wallet corruption cannot alter the current wallet's error behavior; malformed responses and corrupt visible records retain their validation policy.
  • Abort superseded requests and reject stale replies. Typed search debounces for 300 ms; status/date changes apply immediately. URL navigation restores the corresponding search without a pending typed value overwriting it.
  • Scan once, count every match and retain a bounded heap: default 100 rows, maximum 500. Preserve descending creation time, exact ID-string ordering, input order for equal keys, row identity and input immutability.
  • Prepare status, folded search and date cutoff once per query; bypass empty filters. Rows and date windows stay fresh; no result cache is added. Inclusive boundaries and invalid/oversized windows retain their behavior.
  • Repair four maintained fixtures to follow review, confirmation, result and receipt navigation and canonical decimal values. Preserve exact money, no-create, offline, submission-count and retry assertions. An otherwise valid amount with no price now receives the pricing explanation.

Actor identity is additive and stamped on creation. Legacy unscoped records remain visible only to the demo actor. URL parameters and pagination stay compatible. This is the localStorage demonstration API and mock wallet, not an external authorization or settlement service.

Performance evidence

Bounded heap — Node 24.19.0. The 100,000-row shuffled case (100-row cap) measured 776.075 → 26.912 ms, 28.84x, with identical outputs/references. Separate untimed observations counted 3,031,310 → 100,000 timestamp parses and 100,000 → 100 sorted rows. These are medians of five alternating paired samples. All four workloads, raw samples and exact source pins.

Filter preparation — Node 22.23.3. Starting from that optimized heap, the 100,000-row date-window workload measured 77.677 → 41.512 ms (46.56% less time); combined filters measured 37.811 → 26.264 ms (30.54% less). This separate native run used three warmups and nine alternating pairs; outputs/references matched and 10,368 untimed compatibility comparisons passed. All five workloads, executed selector f072d787, source pins and run.

These comparisons use different fixtures/runtimes and are not multiplied into a cumulative speedup. They measure the production selector, excluding storage decoding, validation, simulated API delay, rendering and providers. Both historical benchmarks are preserved without reruns; no whole-page latency or peak-memory claim is made.

Current validation

Source 1e702e6, tree 50b2704afb930440c23d30f6ab1dd7bbbf7fbf85:

  • 504 passed; zero failed/pending/todo/skipped; all 53 files passed, Node 24.19.0 / Vitest 4.1.10. Reported 69.54 s; complete process 70.10 s.
  • Existing formatter check passed, with settings and ignores unchanged.
  • Critical audit on 4 October 2026, 11:56 UTC exited 0: 0 critical, with 20 high / 12 moderate / 2 low remaining. The unchanged package/lock allow that audit to be reused after the final selector composition.
  • Production build passed: 1.75 s Vite / 2.08 s complete command.
  • All 355 tracked files/modes matched the manifest and contents stayed unchanged after execution. No test exclusions, skipped cases or dependency changes.

Full commands, source manifest and raw evidence. Hosted CI and Lighthouse require approval; maintainer acceptance remains pending.

woahwhattheheck and others added 14 commits September 24, 2026 18:03
Make transfer search and filtering deterministic at scale: every list
request carries actor scope, obsolete in-flight queries are aborted,
stable sort + result caps bound work, and stale responses cannot
overwrite the active filter set.
Retire list and create completions when the committed wallet or filter lifecycle changes, including A-to-B-to-A transitions. Obsolete reload callbacks cannot cancel the current query. Same-scope refresh keeps valid creates visible.

Reuse the canonical actor, date, status, sort and cap rules when merging a create, with ID deduplication after ownership validation. A different actor's colliding ID cannot replace the active actor's row.

Validation: 38 focused tests pass across the seven transfer-search suites, including the real delayed localStorage create path; production build and hook lint pass. The full suite still has failures in send-money-form, send-money-precision, offline-reconnect and quote tests; all 12 failed cases also fail on unchanged parent da227b6. No tests were weakened. This remains the existing localStorage demo API, not a provider integration.
The Transfers page remains mounted across wallet changes. Leaving page two
of a seven-transfer wallet for the three-row demo actor previously produced
an empty list and no pagination recovery control. Individual selection and
selection across all pages also leaked across the actor boundary.

Include actorId in the existing reset effect. Keep the committed filter URL
and existing query lifecycle behavior intact. Extend the existing mounted-App
integration file with both selection modes and the A-to-demo-to-A transition.

Validation:
- Both new wallet cases fail on a34be08; affected suites pass 40/40 after.
- Production build and edited-file formatting pass.
- Critical npm audit gate passes; existing lower-severity findings remain.
- Configured production-home Lighthouse collection/assertions pass locally
  (performance 100, accessibility 93); this is not a wallet latency benchmark.
- Required full run: 473 pass, 13 fail. Twelve reproduce in the four existing
  send-money/reconnect/quote files on unchanged a34be08. The extra full-run
  valid-after-invalid timeout passes in its focused candidate rerun.
- Nine repository-wide formatting failures are unchanged baseline files.
No unrelated assertions were changed or disabled.

Continues RemitFlow#298 and issue RemitFlow#281 on the original
contribution branch. Existing localStorage demo scope is unchanged.
Locale collation equates distinct composed/decomposed Unicode IDs. With
identical timestamps, reversing a valid transfer set could therefore choose
a different cap-one member; mixed-case ID order also differed by locale.

Compare the exact ID strings in descending order after the existing
timestamp key. Preserve opaque IDs, filtering, scope, caps and the earlier
hook/page repairs. Add the regression to the existing transfer-search unit
file without changing the eight existing cases.

Actual validation on these source bytes:
- Full production parseTransfer and search imports under English and Turkish
  now give identical sorted/capped members, with six controls per locale.
- The new selected regression fails on parent 7ac632a.
- Existing transfer-search unit file passes 9/9 on the fix with Vitest 4.1.10,
  including the unchanged 5,000-row performance budget.
- Ten retained BEFORE files and four named donor files stayed byte-identical.

This is the existing PR RemitFlow#298 contribution for RemitFlow#281. Full application suite,
build, lint, formatting and hosted CI have not been rerun on this continuation.
Earlier full-suite failures remain documented in the cumulative handoff.
No upstream merge or new PR.
Only user edits schedule debounced URL writes. Query parameters are the committed search authority; history navigation retires an unfinished edit, including same-search status/range changes. Local filter controls preserve an unfinished edit. Clear cancels it before resetting filters. The existing actor scope, result cap, Unicode ordering and wallet-selection fixes are unchanged.

Actual mounted App/BrowserRouter/localStorage API execution: original09cad8 source fails four of six new cases (settled navigation, pending navigation, same-search POP, clear); final source passes6/6 in run37191725198 on Node24.21.0/npm11.19.0/Vitest4.1.10 with locked dependencies. The final burst-of-edits case records exactly one real list call. Earlier candidate additionally passed all10 unchanged transfers-filter cases in run37191485175; its remaining same-search POP failure prompted the location.search dependency correction. No full suite or build result is claimed for this continuation.

Reproduce: npx vitest run test/integration/transfers-search-navigation.test.jsx --maxWorkers=1
Source blob7f5ecbd6d50f92c184e6cc0ccd4e718d34fc0830; regression422ec661894335716f0775f2eae8a99595dfae86. Runner workflow remains isolated outside the original contribution.

Continues PR298 for issue281; no provider integration or payment claim.
Keep the best normalized-limit rows in a bounded heap, parse each matching
timestamp once, and sort only retained results. Preserve exact timestamp/ID
order, stable duplicate membership, sparse inputs, scope and total counts.

Original PR298 continues on its existing branch. Parent17a32681 preserves
the separate navigation repair. Public sort and query dependencies unchanged.

Validation: maintained transfer-search file11/11 with Vitest4.1.10;
independent source review. Five alternating paired samples on Node24.19:
100k shuffled/cap100 median776.075 ->26.912ms (28.84x); 5k22.827 ->2.484ms.
Both ordered100k/cap500 cases improve; complete returned values and object
references match. Repro and raw samples in docs/performance/transfer-search-20261004.

Selector-only result; localStorage parsing, simulated delay, React rendering,
full suite/build/hosted CI and sponsor acceptance are not claimed.

[skip ci]
Issue281 requires existing tests and CI passing without weakening unrelated cases. Reuse the four compatible confirmation/result and canonical-decimal fixtures, preserving all22 existing case titles and exact money, receipt, retry and no-create assertions. Give a valid amount with no available quote the existing pricing explanation instead of an incorrect positive-amount error. Apply only the existing formatter to remaining flagged source/evidence files; configuration and dependency files stay unchanged.

Compose on KESTREL-104's71746fa5 successor. Preserve the exact new selector f072d78, benchmark script1bcf4b3f and maintained testcea83462, plus every historical benchmark value and source pin. The earlier502/52 composition was not published after its non-force update correctly rejected a concurrent source advance; its receipt is retained as an intermediate result.

Final complete package selection on native tree50b2704a:504 passed,0 failed/pending/todo/skipped,53/53files. One run of the final composition:70.096s process, Node24.19.0/Vitest4.1.10. Production build passed:1.75s Vite,2.078s command. Formatting passed. Reuse the11:56:56Z critical-audit result on identical package/lock:0critical,20high,12moderate,2low. No benchmark or audit repeat, install, retry, exclusion, snapshot or timeout change. All355 tracked source blobs remained unchanged after execution.

Exactly19 paths change from71746;336 are unchanged. Original PR298 and all prior contributions/claim custody remain intact. Hosted approval and sponsor acceptance remain separate. Full raw execution evidence follows in a documentation-only child.
Record the final504/53 passing package selection, formatting, production build, and dated critical-threshold audit at source1e702e64. Preserve raw execution output and exact source manifests, with the earlier502/52 composition separately identified after the branch advanced during publication.

This adds only the report, machine-readable receipt and raw evidence archive. All355 tested source blobs/modes and both historical performance reports remain intact. Hosted CI and Lighthouse action_required are recorded separately from passing local gates;34 noncritical audit findings remain.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

perf(frontend): make transfer search and filtering deterministic at scale

1 participant