Fixed stale sidebar member counts after member mutations#28191
Fixed stale sidebar member counts after member mutations#28191jonatansberg wants to merge 4 commits into
Conversation
ref https://linear.app/tryghost/issue/BER-3510/investigate-and-fix-stale-member-count-in-sidebar Member count changes can flow through several admin paths, so imports and Ember member changes now use the existing query invalidation path instead of leaving the sidebar count stale.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
🚧 Files skipped from review as they are similar to previous changes (1)
WalkthroughAdds a typed useImportMembers mutation, import types/type-guards, and a FormData builder; centralizes membersPath and member-count query helpers; introduces an internal useBrowseMembersInfiniteQuery and wraps it with useBrowseMembersInfinite to sync a sidebar member-count cache entry. Refactors ImportMembersModal to call useImportMembers.mutateAsync and handle typed responses/errors. Updates tests to cover API request shape, cache invalidation, sidebar count sync/no-sync cases, Ember bridge invalidation, modal integration, and expanded error handling. Suggested reviewers
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f4b34b7481
ℹ️ 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".
| if (isImportMembersAcceptedResponse(importData)) { | ||
| dispatch({type: 'UPLOAD_ACCEPTED'}); | ||
| onComplete?.(); |
There was a problem hiding this comment.
Defer count invalidation until accepted imports finish
For imports that the server accepts into the background queue, importMembers() has already invalidated MembersResponseType by the time this branch runs, but the actual member rows have not been imported yet. The active sidebar count query will refetch the old total during the PROCESSING state and then be marked fresh again, with no later invalidation when the queued job finishes, so large CSV imports still leave the sidebar count stale after completion.
Useful? React with 👍 / 👎.
ref https://linear.app/tryghost/issue/BER-3510/ The members list can receive a fresher unfiltered total than the lightweight sidebar count query, so the shared members hook now reconciles the existing sidebar cache without page-level wiring.
ref https://linear.app/tryghost/issue/BER-3510/ The sidebar should not need to know that member count is implemented with a lightweight members browse query, so the framework members API now owns the count-specific hook and cache key details.
ref https://linear.app/tryghost/issue/BER-3510/ The behavior coverage is still focused on invalidation, cache reconciliation, and import response handling, but repeated setup has been moved into small helpers so the PR carries less low-signal test diff.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1544451f57
ℹ️ 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".
| export const useImportMembers = createMutation<ImportMembersResponseType, ImportMembersPayload>({ | ||
| method: 'POST', | ||
| path: () => '/members/upload/', | ||
| body: buildImportMembersFormData, | ||
| invalidateQueries: {dataType} |
There was a problem hiding this comment.
Disable retries for member import uploads
When this non-idempotent CSV upload is routed through createMutation, it inherits useFetchApi's default retry = true. In production, a transient network error or lost response after the server has already accepted/processed the POST can cause the same file to be posted again, queueing or applying the import twice; the previous direct fetch did not retry. Please set this mutation's request options to retry: false.
Useful? React with 👍 / 👎.
Summary
MembersResponseTypeinvalidation path.useMemberCount()hook that owns the lightweight/members/?limit=1sidebar count query.useBrowseMembersInfinite()so a fresh unfiltered members-list total updates the existing sidebar count cache when both queries share a query client.Root Cause
Some member-changing paths updated local screen state or used raw upload calls without going through the shared query invalidation mechanics. That left the sidebar's lightweight member-count query stale while the main Members screen could show a newer total.
There was also no shared owner for the sidebar count query shape, so sidebar code knew that member count was implemented as a
limit=1members browse request.Implementation Notes
MembersResponseTypequeries through the existing admin-x-framework mechanics.useMemberCount()from@tryghost/admin-x-framework/api/members, keeping thelimit=1query details inside the framework API.useBrowseMembersInfinite()updates only the existing sidebar count cache entry, and only when the list query is successful, unfiltered, unsearched, non-placeholder/non-previous data, and at least as fresh as the sidebar cache.Validation
pnpm --filter @tryghost/admin-x-framework exec eslint src/api/members.ts test/unit/api/members.test.tsxpnpm exec vitest run test/unit/api/members.test.tsx --coverage=falsepnpm exec tsc --noEmitpnpm --filter @tryghost/admin-x-framework buildpnpm --filter @tryghost/posts exec eslint src/views/members/members.tsxpnpm exec vitest run test/unit/views/members --coverage=falsepnpm --filter @tryghost/admin exec eslint src/layout/app-sidebar/nav-content.tsxref https://linear.app/tryghost/issue/BER-3510/investigate-and-fix-stale-member-count-in-sidebar