feat: Knowledge table optimization (#2202) - #2203
Conversation
* fix: remove page_size cap and fetch all files to fix Knowledge table pagination past 100 files * T1-1 to T1-3 deliverable - file size sort, added check for file_size and chunk_count -10k limit -> 500 file limit -changed hardcoded page size to be controlled by React State; removed client side pagination from AG Grid and wired up custom UI mimicing AG Grid UI * feat: T1-4 server-side sort + T1-6 native AG Grid pagination - Add sortBy/sortOrder state wired to useListFiles (T1-4) - Map AG Grid colId to backend sort field names (size->file_size, etc.) - onSortChanged resets to page 1 on sort change via paginationGoToFirstPage() - Restore AG Grid native pagination UI with pageSize:10000 (T1-6) - T1-2: le=100 backend cap already removed from files.py * v2 API Migration Switched to composite aggregation pagination under v2 * Update page.tsx * fix: remove page_size cap and fetch all files to fix Knowledge table pagination past 100 files * T1-1 to T1-3 deliverable - file size sort, added check for file_size and chunk_count -10k limit -> 500 file limit -changed hardcoded page size to be controlled by React State; removed client side pagination from AG Grid and wired up custom UI mimicing AG Grid UI * feat: T1-4 server-side sort + T1-6 native AG Grid pagination - Add sortBy/sortOrder state wired to useListFiles (T1-4) - Map AG Grid colId to backend sort field names (size->file_size, etc.) - onSortChanged resets to page 1 on sort change via paginationGoToFirstPage() - Restore AG Grid native pagination UI with pageSize:10000 (T1-6) - T1-2: le=100 backend cap already removed from files.py * v2 API Migration Switched to composite aggregation pagination under v2 * Address review feedback: log _get_file_count failures, restore search pagination, mark total as approximate * Git merge fix issues * fix git HEAD * v2 files: add approximate counts & cursor parse Frontend: switch to /api/v2/files, include is_approximate in ListFilesResponse, and disable pagination buttons; removed a debug console.log. Backend API: add _parse_after_key helper to validate JSON-encoded after_key and return 400 for invalid values; use FastAPI Query pattern parameter. FileServiceV2: add embedding_model to composite sort fields, make _get_file_count return (count, is_approximate) and log on failure, use raw bucket count to detect final page, and propagate is_approximate in responses so the UI can display approximate totals. * Refactored component -moved custom footer into its own component * fix merge issues * PR Fixes -changed styling to match Tailwind - footer is now always active, showing regardless of servertotal or wildcardquery -global sort fix * Fix search pagination: route all data through useListFiles, restore search_files page_size cap, reset page on search change * Update page.tsx * update page.tsx * style: ruff autofix (auto) * Lint backend fix * Fix: remove exception detail from error responses to prevent information exposure (git advanced security fix) --------- Co-authored-by: Visvesh Jegadheesh <visveshjega@ibm.com> Co-authored-by: Mike Fortman <mfortman11@gmail.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
WalkthroughThis PR adds v2 file listing and search APIs with composite cursor pagination and approximate totals. The Knowledge page uses server-side pagination and sorting with cursor caching and pagination controls. ChangesFile listing pagination
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant KnowledgePage
participant useListFiles
participant FilesV2API
participant FileServiceV2
participant OpenSearch
KnowledgePage->>useListFiles: request page with sort and after_key
useListFiles->>FilesV2API: GET /api/v2/files
FilesV2API->>FileServiceV2: pass filters, sorting, and cursor
FileServiceV2->>OpenSearch: execute aggregation
OpenSearch-->>FileServiceV2: return files and after_key
FileServiceV2-->>FilesV2API: return files and approximate total
FilesV2API-->>useListFiles: return paginated response
useListFiles-->>KnowledgePage: render rows and pagination footer
Possibly related issues
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ 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 |
|
React Doctor found 1 new issue in 1 file · 1 warning · score 85 / 100 (Great) · 1 fixed · vs 1 warning
Reviewed by React Doctor for commit |
There was a problem hiding this comment.
Actionable comments posted: 9
🧹 Nitpick comments (3)
src/api/v2/files.py (2)
77-86: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winLog the traceback now that the response omits the error detail.
The 500 body no longer carries
detail, which is correct. But the log line records onlystr(e), so the stack trace is lost. Uselogger.exceptionor passexc_info=Trueso the failure remains diagnosable. The same applies to thesearch_fileshandler at Lines 116-125.🤖 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 `@src/api/v2/files.py` around lines 77 - 86, Update the exception logging in the file-listing handler and the search_files handler to include traceback information while keeping the 500 response body free of error details. Replace the current logger.error calls with logger.exception or equivalent exc_info-enabled logging, preserving the existing authentication-error handling and response behavior.
44-58: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick winAdd response model typing to the new v2 endpoints.
Both v2 handlers return a bare
JSONResponse, so FastAPI publishes no schema for them. The frontend already declares the shape inListFilesResponse(frontend/app/api/queries/useListFiles.tsLines 20-27). Declare a Pydantic response model and register it withresponse_modelwhen the route is added insrc/app/routes/internal.py. That makes theis_approximateandafter_keycontract explicit and detects field drift.As per path instructions: "Verify dependency injection via src/dependencies.py, response model typing, and correct HTTP status codes."
🤖 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 `@src/api/v2/files.py` around lines 44 - 58, Define a Pydantic response model for the payload returned by list_files, including the is_approximate and after_key fields matching frontend ListFilesResponse, and register it as response_model when the v2 route is added in internal.py. Verify the handler’s dependency injection remains wired through _get_file_service and get_current_user, and preserve the endpoint’s intended HTTP status codes.Source: Path instructions
src/services/file_service_v2.py (1)
337-362: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winExtract the shared metadata sub-aggregation.
The
file_metadatatop_hitsblock and thechunk_countsub-aggregation are identical here and at Lines 283-308.FileService._build_file_aggregationholds a third copy. A future field addition must be applied in three places. Define one module-level constant and reuse it in both builders.🤖 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 `@src/services/file_service_v2.py` around lines 337 - 362, Extract the repeated file metadata and chunk-count sub-aggregations into one module-level constant, then reuse it in the aggregation builders at the current block, the matching block around the earlier query, and FileService._build_file_aggregation. Preserve the existing top_hits fields, sorting, and chunk-count configuration while ensuring all builders reference the shared definition.
🤖 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 `@frontend/app/knowledge/page.tsx`:
- Around line 348-352: Gate non-first-page requests in the knowledge page’s
pagination flow so they require a cached composite cursor before using afterKey;
update the reactive cursor state when after_key is cached, and pass cursor
availability plus total-approximation state to KnowledgePaginationFooter. In
frontend/app/knowledge/page.tsx lines 348-352, 480-497, and 1128-1136, make
these request, state, and prop changes. In
frontend/components/knowledge-pagination-footer.tsx lines 3-10, 22-23, and
92-99, add the props, stop deriving final-page status solely from totalPages,
disable Next until the current response has a valid cursor, and disable
count-based controls when totals are approximate.
- Around line 377-387: The effectiveData flow must sort non-wildcard search
results before slicing the requested page, using the active sortBy/sortOrder
values; preserve wildcard server ordering by disabling or removing local
comparators for server-sorted columns in wildcard mode.
In `@src/api/v2/files.py`:
- Around line 20-23: Move FileServiceV2 construction out of _get_file_service:
instantiate and retain it in main.py’s lifespan block, expose a dependency
provider through src/dependencies.py, and update the route to inject that
provider instead of importing or constructing FileServiceV2 locally.
- Around line 89-99: Update the page_size Query parameter in search_files to
enforce the same upper bound as list_files, using le=500 while preserving its
existing minimum and default values.
In `@src/services/file_service_v2.py`:
- Around line 44-94: Update list_files so the composite-aggregation path rejects
page values greater than 1 when after_key is None, instead of silently returning
page 1 while reporting the requested page; preserve normal page-1 requests and
cursor-based pagination, and leave the chunk_count path unchanged.
- Around line 394-401: Update the exception path in the file-count retrieval
method to return an unknown or approximate total, such as `(0, True)`, instead
of `(0, False)`. Preserve the warning log and successful aggregation result,
ensuring the API does not treat a failed count as an exact total that disables
pagination.
- Around line 96-128: Add is_approximate: False to the fallback return
dictionary in the file-listing method’s opensearch exception path, keeping it
consistent with the success return and ensuring failed empty results are
reported as exact.
- Around line 313-336: The chunk-count terms aggregation in
_build_terms_aggregation_for_chunk_count must not request unbounded offset +
page_size buckets; enforce a safe maximum (or use cursor pagination) before
assigning the terms size, while preserving page slicing. Update nearby
documentation and any global/accurate-order claims to describe the results as
approximate unless the bounded aggregation configuration guarantees otherwise,
consistent with is_approximate=True.
- Around line 255-272: The _build_composite_aggregation method currently omits
documents missing the selected sort field or filename tie-breaker. Add
missing_bucket: true to the terms definitions for both the primary sort source
and the filename_tiebreak source, preserving existing field and order settings
so missing file_size, embedding_model, mimetype, and owner documents remain in
results.
---
Nitpick comments:
In `@src/api/v2/files.py`:
- Around line 77-86: Update the exception logging in the file-listing handler
and the search_files handler to include traceback information while keeping the
500 response body free of error details. Replace the current logger.error calls
with logger.exception or equivalent exc_info-enabled logging, preserving the
existing authentication-error handling and response behavior.
- Around line 44-58: Define a Pydantic response model for the payload returned
by list_files, including the is_approximate and after_key fields matching
frontend ListFilesResponse, and register it as response_model when the v2 route
is added in internal.py. Verify the handler’s dependency injection remains wired
through _get_file_service and get_current_user, and preserve the endpoint’s
intended HTTP status codes.
In `@src/services/file_service_v2.py`:
- Around line 337-362: Extract the repeated file metadata and chunk-count
sub-aggregations into one module-level constant, then reuse it in the
aggregation builders at the current block, the matching block around the earlier
query, and FileService._build_file_aggregation. Preserve the existing top_hits
fields, sorting, and chunk-count configuration while ensuring all builders
reference the shared definition.
🪄 Autofix
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: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 69fc7988-0f2f-460e-8f8e-b26bcf557c0d
📒 Files selected for processing (9)
frontend/app/api/queries/useListFiles.tsfrontend/app/knowledge/page.tsxfrontend/components/knowledge-pagination-footer.tsxsrc/api/files.pysrc/api/v2/__init__.pysrc/api/v2/files.pysrc/app/routes/internal.pysrc/services/file_service.pysrc/services/file_service_v2.py
…ge guard, search_files page_size cap
-Improved exception handling by chaining the original error. -Refactored FileServiceV2 to use dependency injection instead of creating it in routes -Optimized cursor cache initialization with lazy Map creation -Fixed infinite re-render caused by search reset effect
fix: remove page_size cap and fetch all files to fix Knowledge table pagination past 100 files
T1-1 to T1-3 deliverable
-changed hardcoded page size to be controlled by React State; removed client side pagination from AG Grid and wired up custom UI mimicing AG Grid UI
Switched to composite aggregation pagination under v2
Update page.tsx
fix: remove page_size cap and fetch all files to fix Knowledge table pagination past 100 files
T1-1 to T1-3 deliverable
-changed hardcoded page size to be controlled by React State; removed client side pagination from AG Grid and wired up custom UI mimicing AG Grid UI
Switched to composite aggregation pagination under v2
Address review feedback: log _get_file_count failures, restore search pagination, mark total as approximate
Git merge fix issues
fix git HEAD
v2 files: add approximate counts & cursor parse
Frontend: switch to /api/v2/files, include is_approximate in ListFilesResponse, and disable pagination buttons; removed a debug console.log. Backend API: add _parse_after_key helper to validate JSON-encoded after_key and return 400 for invalid values; use FastAPI Query pattern parameter. FileServiceV2: add embedding_model to composite sort fields, make _get_file_count return (count, is_approximate) and log on failure, use raw bucket count to detect final page, and propagate is_approximate in responses so the UI can display approximate totals.
-moved custom footer into its own component
fix merge issues
PR Fixes
-changed styling to match Tailwind
Fix search pagination: route all data through useListFiles, restore search_files page_size cap, reset page on search change
Update page.tsx
update page.tsx
style: ruff autofix (auto)
Lint backend fix
Fix: remove exception detail from error responses to prevent information exposure (git advanced security fix)
Summary by CodeRabbit
New Features
Bug Fixes