fix(admin): order mutations never invalidated the paginated orders cache#273

merged2
main
fix/admin-order-cache-keys
openedAug 22, 2026byAAviddaram
View on GitHubTwo-way sync enabledPR last imported 20d ago

Problem

Every consumer of order.getPaginatedOrders queries with real inputs (page, filters, sort). Every invalidation used queryOptions({}) / queryKey({}), which hashes the empty input into the key. tRPC query keys are [path, { input, type }], so prefix matching died at the input element: none of the ~10 invalidation call sites ever matched a mounted query. The 15s polling in orders-list masked it.

Also fixes two adjacent bugs found on the same paths:

  • order-form.tsx spread an array into an object ({ ...queryKey }), producing garbage filters that invalidated the entire cache on every order update
  • the optimistic delete in order-card.tsx canceled/snapshotted/patched zero entries (same key mismatch) โ€” dead code, now removed

Changes

  • all getPaginatedOrders invalidations โ†’ .pathFilter()
  • drop dead optimistic-delete block; keep toasts + settle invalidation
  • polling 15s โ†’ 60s now that invalidations actually work

Verification

  • typecheck (tsgo) clean
  • manual: change order status while list is filtered/sorted โ†’ updates without waiting for poll

Checks

4 successful ยท 1 skipped
All checks passed
6e3a32c

Added 1 commit

  • fix(admin): invalidate every getPaginatedOrders cache entry, not just empty-inputf347868
Synced from GitHub

Important

  • ๐Ÿ” Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

โš™๏ธ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: a7a1bb86-764e-46db-b564-b713490c2186


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

โค๏ธ Share

Comment @coderabbitai help to get the list of available commands.

Cchatgpt-codex-connectorBotreviewed ยท 1 inline threadAug 22, 2026
Synced from GitHub

๐Ÿ’ก Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f347868660

โ„น๏ธ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with ๐Ÿ‘.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

apps/admin/src/components/order/orders-list.tsxline 98Outdated ยท f347868Open thread
โ€ฆโ€ฆ@@ -95,7 +95,7 @@ export default function OrdersList({
9696 date,
9797 }),
98- refetchInterval: 15_000,
98+ refetchInterval: 60_000,

P2 Badge Invalidate detail edits before slowing list polling

When an admin changes the payment status or customer fields from the order-detail page and returns to the list within its 30-second stale window, updateOrderField and patchOrderHeader only invalidate getOrderById (orders.$id.tsx:195-210), so the cached paginated list still shows the old values. Increasing this interval from 15 to 60 seconds therefore stretches the only corrective refresh for those mutation paths to as much as a minute; invalidate getPaginatedOrders from those handlers before reducing the polling frequency.

Useful? React with ๐Ÿ‘ย / ๐Ÿ‘Ž.

Synced from GitHub

Greptile Summary

This PR replaces input-specific paginated-order invalidations with procedure path filters, removes ineffective optimistic-delete cache handling, and reduces polling frequency now that the primary mutation paths actively refresh lists.

  • Uses pathFilter() to invalidate every getPaginatedOrders input variant.
  • Retains delete notifications and settled reconciliation without the ineffective optimistic patch.
  • Increases list polling from 15 seconds to 60 seconds, although several adjacent mutations still rely on that fallback.

Confidence Score: 4/5

The polling increase should be fixed or the remaining order mutation paths should adopt path-wide invalidation before merging, otherwise users can see stale order data for up to a minute.

The converted invalidations correctly target parameterized order-list queries, but transfer-payment and detail-page edit paths still miss those caches, and the changed polling interval materially extends their stale-data window.

Files Needing Attention: apps/admin/src/components/order/orders-list.tsx, apps/admin/src/components/order/pending-transfer-dialog.tsx, apps/admin/src/routes/_dash/orders.$id.tsx

Important Files Changed

FilenameOverview
apps/admin/src/components/order/order-card.tsxConverts status, delete, and shipping callbacks to path-wide invalidation and removes an ineffective optimistic-delete block.
apps/admin/src/components/order/order-form.tsxReplaces malformed paginated-cache invalidation with a procedure path filter after order updates.
apps/admin/src/components/order/orders-list.tsxCorrects batch invalidations but increases fallback polling to 60 seconds while uncovered mutation paths remain.
apps/admin/src/routes/_dash/orders.$id.tsxCorrects paginated invalidation for deletion, status changes, and shipping, while adjacent inline-edit mutations still omit it.
apps/admin/src/routes/_dash/orders.add.tsxInvalidates all paginated-order query variants after successful order creation.

Flowchart

mermaid
1%%{init: {'theme': 'neutral'}}%%
2flowchart LR
3 M[Order mutation succeeds] --> I{Uses paginated pathFilter?}
4 I -->|Yes| R[All mounted list variants refetch]
5 I -->|No or empty-input key| P[Wait for polling or window focus]
6 P --> S[Mounted list may remain stale up to 60 seconds]

Reviews (1): Last reviewed commit: "fix(admin): invalidate every getPaginate..." | Re-trigger Greptile

apps/admin/src/components/order/orders-list.tsxline 98Outdated ยท f347868Open thread
โ€ฆโ€ฆ@@ -95,7 +95,7 @@ export default function OrdersList({
9696 date,
9797 }),
98- refetchInterval: 15_000,
98+ refetchInterval: 60_000,
Ggreptile-appsBoton line 98Aug 22, 2026

P1 Polling now masks missed invalidations

When an admin confirms or rejects a transfer payment or edits payment status or order-header fields from the detail page, those paths still use an empty-input key or omit paginated-list invalidation. Increasing this fallback interval therefore leaves mounted lists showing outdated fields or filter membership for up to 60 seconds instead of 15 seconds.

suggestion
1 refetchInterval: 15_000,

Added 1 commit

  • fix(admin): detail-page order writes also invalidate the orders list6e3a32c
Cchatgpt-codex-connectorBotreviewed ยท 1 inline threadAug 22, 2026
Synced from GitHub

๐Ÿ’ก Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6e3a32c379

โ„น๏ธ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with ๐Ÿ‘.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

โ€ฆโ€ฆ@@ -95,7 +95,7 @@ export default function OrdersList({
9696 date,
9797 }),
98- refetchInterval: 15_000,
98+ refetchInterval: 60_000,

P2 Badge Keep frequent polling for externally created orders

When a customer completes checkout through apps/storev2 or the Messenger agent creates an order, that write occurs outside this dashboard's QueryClient, so none of the new invalidations run. If the orders page remains focused, polling is still its only way to discover the order; increasing this interval delays newly placed orders by up to 60 seconds instead of 15 seconds. Keep the previous cadence unless cross-client invalidation or server-pushed updates are added.

Useful? React with ๐Ÿ‘ย / ๐Ÿ‘Ž.

Addressed both findings in 6e3a32c: updateOrderField, patchOrderHeader (and the ship dialog path) now invalidate the paginated list via pathFilter(). The transfer-claim path was already covered โ€” pending-transfer-dialog.tsx uses input-less queryKey(), which prefix-matches all inputs.