fix: economicResources.pageInfo.totalCount ignored pagination limit - #69
Merged
Merged
Conversation
Zenflows.GQL.Connection.from_list/2 computes total_count by counting
the records actually fetched for the current page (bounded by
first/last, plus the +1 peek row used to detect hasNextPage) — not a
real count of everything matching the filter. That's deliberate,
tested behavior for the generic Connection/Page pagination shared by
every connection in the schema (see test/db/page.test.exs), but it
means economicResources' totalCount silently caps at whatever page
size the client asked for: requesting `last: 12` always reports
totalCount: 12, even when far more rows match, and hasNextPage: true
in the same response proves it.
This is a real discrepancy against the field's own documented
contract ("The total result count, if it can be determined.") for a
type where the count is client-visible product/service/design
inventory totals.
Fix: mirror the existing count_distinct_primary_accountable/1 pattern
(EconomicResource.Query.filtered_query/1 + an unbounded aggregate
query) with a new EconomicResource.Query.count/1 /
EconomicResource.Domain.count/1, and have
EconomicResource.Resolv.economic_resources/2 override
page_info.total_count with it — same way distinct_primary_accountable_count
is already added. Scoped to economic_resources only, not a change to
the shared Connection module, so every other paginated type (agents,
proposals, etc.) keeps its existing, tested, page-bound behavior.
Tests: new EconomicResource.Domain "count/1" test and a GQL-level
EconomicResource.Type test that requests first: 2 against 5 matching
resources and asserts totalCount == 5 (not 2) while
distinctPrimaryAccountableCount == 1. Ran the full suite locally
(mix test, 568 tests) against a throwaway Postgres container: 6
pre-existing failures (env-config artifacts of the throwaway
ADMIN_KEY/ROOM_SALT setup, plus one unrelated nil-classified_as bug
in classifications/1) reproduce identically on unmodified master;
zero regressions from this change. mix credo also clean for the
touched files.
phoebus-84
had a problem deploying
to
test_trace
September 4, 2026 14:19 — with
GitHub Actions
Failure
phoebus-84
added a commit
to interfacerproject/interfacer-gui
that referenced
this pull request
Sep 4, 2026
## Summary Picks up [`interfacer-client#1`](interfacerproject/interfacer-client#1), which adds `distinctPrimaryAccountableCount` to `FETCH_RESOURCES`'s `pageInfo` selection. Combined with [`zenflows#69`](interfacerproject/zenflows#69) (fixes `economicResources.pageInfo.totalCount` to reflect the real filtered total instead of just the page size), this fixes the catalogue pages' hero stats: | | before | after | |---|---|---| | Total Products | 12 (= page size requested) | **121** (real total) | | Manufacturers | 0 | **2** (real distinct count) | ## Changes - `package.json`: `@dyne/interfacer-client` `^0.6.0` → `^0.6.1` - `pnpm-lock.yaml`: updated accordingly No source code changes — dependency bump only. ## Testing - `pnpm check-types` — clean - `pnpm check-format` — clean - Verified live: restarted the dev server against the bumped dependency and confirmed `/products` now shows "121 Total Products" / "2 Manufacturers" (previously "12" / "0"), with the real GraphQL response now carrying the fixed fields end-to-end from `zenflows` → `interfacer-client` → `interfacer-gui`. ## Related - #893 (catalogue heading rework — independent, this PR is branched off `main`, not off that branch) - interfacerproject/interfacer-client#1 - interfacerproject/zenflows#69 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: euripide <euripide@MacBook-Air-di-euripide.local>
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.
Summary
Zenflows.GQL.Connection.from_list/2computestotal_countby counting the records actually fetched for the current page (bounded byfirst/last, plus the+1peek row used to detecthasNextPage) — not a real count of everything matching the filter. That's deliberate, tested behavior for the genericConnection/Pagepagination shared by every connection in the schema (seetest/db/page.test.exs, which has a whole comment block documenting "totalCount depends on num"). But it meanseconomicResources'totalCountsilently caps at whatever page size the client asked for: requestinglast: 12always reportstotalCount: 12, even when far more rows match — andhasNextPage: truein the same response proves it.Verified live against
https://proxy.dpp-dev.ddns.dyne.org/zenflows/api:This is a real discrepancy against the field's own documented contract (
@desc "The total result count, if it can be determined.") for a type where the count is client-visible product/service/design inventory totals (interfacer-gui's "Showing X results").Fix
Mirrors the existing
count_distinct_primary_accountable/1pattern (EconomicResource.Query.filtered_query/1+ an unbounded aggregate query):EconomicResource.Query.count/1— new, unboundedCOUNT(*)over the filtered queryEconomicResource.Domain.count/1— thin wrapperEconomicResource.Resolv.economic_resources/2— overridespage_info.total_countwith it, the same waydistinct_primary_accountable_countis already addedScoped to
economic_resourcesonly — this is not a change to the sharedConnectionmodule, so every other paginated type (agents, proposals, etc.) keeps its existing, tested, page-bound behavior. Changing that generically would touch ~25 other resolvers and contradict the existingtest/db/page.test.exscontract; onlyeconomic_resourcesgets the extra accuracy, matching how it already gets the extradistinctPrimaryAccountableCountquery.Testing
Set up a full local toolchain to actually run this (Elixir 1.14.5/OTP 25 via
mise, throwaway Postgres in Docker):EconomicResource.Domain "count/1"test and a GQL-levelEconomicResource.Typetest that requestsfirst: 2against 5 matching resources and assertstotalCount == 5(not 2) whilehasNextPage == trueanddistinctPrimaryAccountableCount == 1— reproduces the exact bug shape, both pass.mix test→ 568 tests, 6 failures. Confirmed by stashing and re-running that the same 6 failures reproduce identically on unmodifiedmaster(artifacts of the throwawayADMIN_KEY/ROOM_SALTtest env, plus one pre-existing unrelated nil-classified_asbug inclassifications/1) — zero regressions from this change.mix credo— clean on the touched files.🤖 Generated with Claude Code