Skip to content

feat(sdk): read post tips over GET and align pro-members freshness - #1273

Merged
feruzm merged 3 commits into
developfrom
feature/private-api-client-cache
Jul 29, 2026
Merged

feat(sdk): read post tips over GET and align pro-members freshness#1273
feruzm merged 3 commits into
developfrom
feature/private-api-client-cache

Conversation

@feruzm

@feruzm feruzm commented Jul 29, 2026

Copy link
Copy Markdown
Member

Client half of #1272. Server half is ecency/vision-api#61.

Post tips were fetched with a POST. A POST response is uncacheable by definition, so the same totals were re-requested on every mount, and getPostTipsQueryOptions also had no staleTime (defaulting to 0, i.e. stale on every mount and window refocus). The endpoint keys off nothing but author and permlink and needs no auth, so there was never a reason for it to be a POST.

Changes

  • post-tips now reads as GET /private-api/post-tips/{author}/{permlink}. Both segments go through encodeURIComponent, so a permlink cannot change which resource is addressed. staleTime set to the endpoint's fresh window.
  • pro-members staleTime 5m to 10m, matching its fresh window. A shorter one only makes react-query re-ask for a roster the browser already holds now that the response carries a Cache-Control.
  • announcements needs no change here; its 1h staleTime already sits above the server window.

staleTime alone would not have helped much: it dedupes within a session, while the Cache-Control from #61 is what stops the refetch on the next page load. The two are paired on purpose.

Merge order

This must not be published before ecency/vision-api#61 is deployed. Without the GET route, the request falls through to the unmatched-GET template page, which is a 200 whose body fails to parse as JSON, so the query errors rather than degrading. The POST route stays in place server-side, so nothing breaks in the other direction.

Note both web and mobile consume these through @ecency/sdk (tipsQueries.ts and proQueries.ts in ecency-mobile), so mobile picks the change up on its next SDK bump rather than needing its own patch.

Verification

  • SDK: typecheck clean, lint clean, 592 tests pass, including 5 new ones covering the verb, the path encoding, the enabled guard and error propagation.
  • Web: entry-tip-btn and pro-config specs pass.

The new spec pins the verb and URL shape deliberately: a regression back to a POST, or an unencoded permlink, is invisible in the UI and costs every reader a round trip per mount.

Summary by CodeRabbit

  • Improvements
    • Pro member roster caching is now aligned with the private endpoint refresh window, keeping data fresh while avoiding extra refreshes.
    • Post tips are now fetched via a cacheable GET request with properly URL-encoded author and permlink.
    • Post tips results are cached for 60 seconds and won’t run until both author and permlink are provided.
    • Clear errors continue to be shown when post-tip data can’t be retrieved.
  • Tests
    • Added coverage for the post tips request contract, caching, enablement behavior, and error propagation.

Post tips were fetched with a POST, which no cache may store, so the same
totals were re-requested on every mount. The endpoint keys off nothing but
author and permlink and needs no auth, so it is now read as a GET on a URL
and can be served from the browser cache.

- post-tips: POST body -> GET path segments, both encodeURIComponent'd so a
  permlink cannot alter which resource is addressed. staleTime added; it was
  unset, meaning stale on every mount and window refocus.
- pro-members: staleTime 5m -> 10m to match the roster's fresh window, so
  react-query stops re-asking for a list the browser already holds.

Requires the GET route to be live server-side first: without it the request
falls through to the unmatched-GET template page, which is a 200 that fails
to parse as JSON. Web and mobile both consume these through the SDK.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cbec038cd2

ℹ️ 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".

return response.json() as Promise<ProMembersResponse>;
},
staleTime: 5 * 60 * 1000,
staleTime: 10 * 60 * 1000,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Account for the response's existing cache age

When a page reload creates a new QueryClient while the browser already has, for example, a nine-minute-old pro-members response, fetch returns that cached response but React Query records it as freshly fetched and waits another ten minutes. A membership change can therefore remain hidden for nearly twenty minutes—well beyond the endpoint's ten-minute window, and up to five minutes longer than with the previous setting. Keep the shorter staleTime or derive the remaining freshness from the response's Age/cache metadata instead of restarting the full server window.

Useful? React with 👍 / 👎.

@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 6d721800-9744-4cd7-a7ee-eb11e0463f78

📥 Commits

Reviewing files that changed from the base of the PR and between cbec038 and 852b50d.

⛔ Files ignored due to path filters (7)
  • packages/sdk/dist/browser/index.d.ts is excluded by !**/dist/**
  • packages/sdk/dist/browser/index.js is excluded by !**/dist/**
  • packages/sdk/dist/browser/index.js.map is excluded by !**/dist/**, !**/*.map
  • packages/sdk/dist/node/index.cjs is excluded by !**/dist/**
  • packages/sdk/dist/node/index.cjs.map is excluded by !**/dist/**, !**/*.map
  • packages/sdk/dist/node/index.mjs is excluded by !**/dist/**
  • packages/sdk/dist/node/index.mjs.map is excluded by !**/dist/**, !**/*.map
📒 Files selected for processing (7)
  • packages/sdk/CHANGELOG.md
  • packages/sdk/package.json
  • packages/sdk/src/modules/accounts/queries/get-pro-members-query-options.ts
  • packages/sdk/src/modules/posts/queries/get-post-tips-query-options.spec.ts
  • packages/sdk/src/modules/posts/queries/get-post-tips-query-options.ts
  • packages/wallets/CHANGELOG.md
  • packages/wallets/package.json

📝 Walkthrough

Walkthrough

The SDK now retrieves post tips through an encoded, cacheable GET request with expanded tests. Pro-members caching documentation and SDK and wallets release metadata were updated.

Changes

SDK query update

Layer / File(s) Summary
Post-tips GET request and validation
packages/sdk/src/modules/posts/queries/get-post-tips-query-options.ts, packages/sdk/src/modules/posts/queries/get-post-tips-query-options.spec.ts
Post tips use an encoded GET path, a 60-second stale time, identifier-based enablement, and tested non-OK response handling.
Pro-members freshness documentation
packages/sdk/src/modules/accounts/queries/get-pro-members-query-options.ts
The documentation now explains React Query staleness relative to endpoint and browser cache windows.
Package release metadata
packages/sdk/package.json, packages/sdk/CHANGELOG.md, packages/wallets/package.json, packages/wallets/CHANGELOG.md
SDK and wallets patch versions and changelog entries are updated to 2.3.68 and 5.0.68.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant QueryOptions
  participant Fetch
  participant PostTipsEndpoint
  QueryOptions->>Fetch: GET encoded author/permlink path
  Fetch->>PostTipsEndpoint: Request post tips
  PostTipsEndpoint-->>Fetch: JSON response or HTTP error
  Fetch-->>QueryOptions: Parsed response or thrown error
Loading

Possibly related issues

Possibly related PRs

Poem

A rabbit hops where tip requests meet,
GET paths make the trail complete.
Fresh cache clocks begin to chime,
Tests guard every hop in time.
New releases shine like carrots sweet!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main SDK change: fetching post tips over GET and adjusting pro-members freshness.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/private-api-client-cache

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/sdk/src/modules/accounts/queries/get-pro-members-query-options.ts`:
- Around line 17-18: Update the staleTime explanation near the cache-control
comment to state that a longer staleTime keeps the cached roster fresh longer
and delays refetches after the endpoint’s server-side cache window expires;
remove the implication that it causes stale badges sooner.

In `@packages/sdk/src/modules/posts/queries/get-post-tips-query-options.spec.ts`:
- Around line 49-51: Update the test for getPostTipsQueryOptions to assert that
staleTime is exactly 60 seconds, rather than merely greater than zero, so it
verifies the required server-cache freshness window.
- Line 17: Update the fetchMock definition in the get-post-tips query options
test to avoid unused _url and _init parameters, using a typed zero-argument mock
while preserving the existing typed call inspection and mock response behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 84571ecb-003f-43ae-90dc-a57a522aa493

📥 Commits

Reviewing files that changed from the base of the PR and between 6ec3d26 and cbec038.

📒 Files selected for processing (3)
  • packages/sdk/src/modules/accounts/queries/get-pro-members-query-options.ts
  • packages/sdk/src/modules/posts/queries/get-post-tips-query-options.spec.ts
  • packages/sdk/src/modules/posts/queries/get-post-tips-query-options.ts

Comment thread packages/sdk/src/modules/accounts/queries/get-pro-members-query-options.ts Outdated
// an argument-less mock infers an empty tuple and asserting on it needs a cast
// that would pass whatever it was given.
function captureRequest(response: unknown = { tips: [] }) {
const fetchMock = vi.fn(async (_url: string, _init?: RequestInit) => ({

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Remove the unused mock parameters.

_url and _init trigger the reported ESLint errors, so this suite will not meet the clean-lint requirement. Consume them or replace the implementation with a typed zero-argument mock while retaining typed call inspection.

Proposed fix
-    const fetchMock = vi.fn(async (_url: string, _init?: RequestInit) => ({
-      ok: true,
-      status: 200,
-      json: async () => response,
-    }));
+    const fetchMock = vi.fn(async (_url: string, _init?: RequestInit) => {
+      void _url;
+      void _init;
+      return {
+        ok: true,
+        status: 200,
+        json: async () => response,
+      };
+    });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const fetchMock = vi.fn(async (_url: string, _init?: RequestInit) => ({
const fetchMock = vi.fn(async (_url: string, _init?: RequestInit) => {
void _url;
void _init;
return {
ok: true,
status: 200,
json: async () => response,
};
});
🧰 Tools
🪛 ESLint

[error] 17-17: '_url' is defined but never used.

(@typescript-eslint/no-unused-vars)


[error] 17-17: '_init' is defined but never used.

(@typescript-eslint/no-unused-vars)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/sdk/src/modules/posts/queries/get-post-tips-query-options.spec.ts`
at line 17, Update the fetchMock definition in the get-post-tips query options
test to avoid unused _url and _init parameters, using a typed zero-argument mock
while preserving the existing typed call inspection and mock response behavior.

Source: Linters/SAST tools

Comment thread packages/sdk/src/modules/posts/queries/get-post-tips-query-options.spec.ts Outdated
Raising pro-members staleTime to match the server window was wrong. react-query
cannot see how old a response already was when fetch served it from the browser
cache, so it treats a nine-minute-old body as freshly fetched and starts its own
window from zero. Worst-case staleness is the two windows added together, so
matching them roughly doubles it instead of aligning them. Reverted to 5m and
documented the reasoning on both queries.

Also assert the exact post-tips window in the spec: toBeGreaterThan(0) passes
for a 1ms staleTime, which is the very bug the test is meant to catch.
@feruzm

feruzm commented Jul 29, 2026

Copy link
Copy Markdown
Member Author

Thanks both. Triage:

Codex, Age-unaware staleTime — valid, fixed. This was the substantive one. react-query cannot see how old a response already was when fetch served it from the browser cache, so it treats a nine-minute-old body as freshly fetched and restarts its own window. Worst case is the two windows added together, so raising staleTime to match the server roughly doubles staleness instead of aligning it. Reverted to 5m, and the reasoning is now documented on both queries so it does not get "helpfully" raised again.

CodeRabbit, exact freshness assertion — valid, fixed. toBeGreaterThan(0) passing for a 1ms window would miss precisely the bug the test exists to catch. Now asserts 60 * 1000.

CodeRabbit, unused mock parameters cause ESLint errors — not reproducible, no change. no-unused-vars and @typescript-eslint/no-unused-vars are both set to 0 (off) in this package's resolved config, eslint on that exact file exits 0, and the lint (24.x) check passed on this PR. The parameters are also load-bearing: an argument-less vi.fn() infers an empty tuple for mock.calls, so asserting on the fetch arguments would need a cast that passes regardless of what fetch was actually called with. Happy to revisit with a failing lint run.

CodeRabbit, stale-time wording — superseded. Both comments were rewritten for the revert above.

@feruzm feruzm added the patch Bug fixes and patches (1.0.0 → 1.0.1) label Jul 29, 2026
@feruzm
feruzm merged commit 370f7ac into develop Jul 29, 2026
3 of 4 checks passed
@feruzm
feruzm deleted the feature/private-api-client-cache branch July 29, 2026 15:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

patch Bug fixes and patches (1.0.0 → 1.0.1)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant