Skip to content

Batch price history requests instead of one per EAN per day #45

Description

@OffCrazyFreak

What needs to change

Shopping list price history issues one request per EAN per day. A long list over a wide period multiplies into hundreds of round trips. It needs a batched or ranged fetch.

Where

frontend/src/app/(user)/shopping-lists/[id]/components/price-history/use-shopping-list-price-history.ts:35

const queries = useQueries({
  queries: eans.flatMap((ean) =>
    dates.map((date, index) => ({
      queryKey: ["cijene", "product", "history", ean, date],
      queryFn: () => cijeneService.getProductByEan({ ean, date }),
      enabled: !!ean,
      staleTime:
        index === 0 || index === dates.length - 1
          ? 60 * 1000
          : 6 * 60 * 60 * 1000,
    })),
  ),
});

Current and expected behaviour

Now: the request count is eans.length * dates.length. A 20 item list on the 1M period is roughly 600 requests for one chart. This is the reason the 1Y and ALL periods are disabled repo-wide (see DISABLED_PERIODS), so the cap is hiding the problem rather than solving it. The same shape exists for a single product in frontend/src/lib/cijene-api/hooks.ts (usePriceHistory), just without the EAN multiplier.

Should be: one request covers many days, and ideally many EANs, so the count grows with lists rather than with list size times day count.

Done when

  • Opening price history for a multi-item list issues a bounded number of requests that does not scale with the number of days
  • The chart renders the same data as before for the 1W and 1M periods
  • The single-product path in lib/cijene-api/hooks.ts gets the same treatment, so the two do not drift
  • pnpm exec tsc --noEmit stays clean

Constraints and gotchas

  • The staggered staleTime is deliberate: the first and last day of the window are volatile (60s), interior days are effectively immutable (6h). Preserve that distinction, or the cache will re-fetch settled history.
  • groupPriceHistoriesByEan(..., dates.length) relies on positional holes to represent days with no snapshot. A missing day is not a price of zero and must not be collapsed, or the chart will draw a fake drop.
  • buildDateWindow() in frontend/src/utils/date.ts is the single source for the requested window and handles local-time boundaries. Keep using it rather than recomputing dates.
  • Do not re-enable the long periods as part of this. That is tracked separately in Enable price history periods longer than 30 days #62 and depends on the same upstream change.

Blocked on

Self-hosting the price API, so it can expose a range or batch endpoint. Same dependency as #62.

Affected area

Frontend (web / PWA)


From the dev-vs-main code review (finding #38). #62 is the same upstream change seen from the feature side: one range endpoint resolves both.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requesttech-debtCode health and maintainability

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions