feat: migrate from unstable_cache to use cache, cleanup SSR prefetch stub#69
Merged
Merged
Conversation
Replace over-specified fake DemoSource with a minimal SourceView since toParsedChunkView only uses title and documentId. Extract magic page size 100 to a named constant aligned with the client-side page size (50). Add cache tags for future on-demand invalidation and a migration note for "use cache" when cacheComponents is enabled.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
1 Skipped Deployment
|
Enable cacheComponents in next.config.ts and replace the unstable_cache
wrapper with a "use cache" async function using cacheLife("max") and
cacheTag("demo-chunks", demoSourceId). The cache key is now automatically
derived from the function's arguments rather than manually specified.
The home page is restructured with a Suspense boundary so the static
shell can be prerendered while dynamic content (auth, guest context)
streams in at request time via connection().
connection() can't be called in test environment (no request scope). Extract the render logic into an exported renderWorkspaceShell() so the test can exercise the data-fetching path without triggering the connection() boundary.
Replace the fetch-level cache:force-cache with "use cache" directives
at the async wrapper layer in knowhere-demo.ts. This catches all callers
(SSR page, API routes) and integrates with Next.js 16's cache tagging
for on-demand invalidation.
- fetchCatalog: cacheLife("hours") + cacheTag("demo-catalog")
- fetchChunkPage: cacheLife("hours") + cacheTag("demo-chunks", id)
The outer "use cache" in initial-state.ts is removed since the
integration layer now handles caching. Effect functions are exported
so tests can call them without triggering cacheLife().
Both functions call Dashboard oRPC endpoints on every SSR request. Caching for "minutes" (1-minute revalidate) reduces Dashboard load for rapid repeat requests while keeping session data reasonably fresh. - getCurrentUser: cookie read extracted to outer function, Effect execution moved to cached inner function getCurrentUserCached - fetchKnowhereJwt: Effect execution moved to cached inner function fetchKnowhereJwtCached (cookieHeader already an explicit argument) - Tests mock next/cache as no-ops since cacheLife/cacheTag require the Next.js runtime
The cached function was calling getCurrentUserEffect which reads headers() internally, ignoring the cookieHeader parameter. This meant the cache key was always empty — the first user's session would be returned for all subsequent users. Extract callGetCurrentUser(cookieHeader) as a shared Effect so the cached path uses the explicit cookie header (different cache key per session) while getCurrentUserEffect continues to read headers() for the Auth service layer.
The login page reads headers() to resolve the Notebook public URL for the Dashboard callback. With cacheComponents enabled, request-time APIs must be wrapped in a Suspense boundary with connection(). Extracts renderLoginPage() for testability — tests call it directly to avoid the connection() call which requires Next.js runtime.
- Export HomeContent/LoginContent directly instead of renderWorkspaceShell/ renderLoginPage wrappers. Tests mock next/server (connection) so the components work without Next.js runtime. - Un-export fetchCatalogEffect/fetchChunkPageEffect. Tests mock next/cache (cacheLife/cacheTag) so knowhereDemoApi.fetchChunkPage works directly. - Add comment documenting the fixed 1-min JWT cache vs. expiresInSeconds tradeoff.
findCitationSource matches source.documentId === citation.source.documentId, but these were populated from different API fields: - source.documentId <- canonical_document_id - citation.source.documentId <- source.document_id (nested) When the demo API returns different values for these fields, the lookup returns null and citation clicks silently do nothing. Use the citation's canonicalDocumentId instead, which maps to the same canonical_document_id field as the source.
SSR-prefetched chunks bypassed resolveChunkConnectionTargets, leaving targetChunkId null on all chunk-to-chunk references. With isResolved === false, the reference buttons were disabled in the chunks panel. Wrap prefetched chunks through resolveChunkConnectionTargets so cross- chunk references are clickable in guest mode.
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.
Clean up issues from #67 and migrate from unstable_cache to the use cache directive.