Skip to content

feat(approvals): server-side pagination + search pushdown for listRequests#1764

Merged
os-zhuang merged 1 commit into
mainfrom
feat-approvals-server-pagination
Jun 12, 2026
Merged

feat(approvals): server-side pagination + search pushdown for listRequests#1764
os-zhuang merged 1 commit into
mainfrom
feat-approvals-server-pagination

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Summary

Closes the dangerous half of #1745 — beyond the 500-row scan cap the inbox silently lost rows. Console companion: objectstack-ai/objectui#1658 (merged).

  • q pushdown: free-text search becomes an $or of $contains (escaped-LIKE) terms over process_name / object_name / record_id / submitter_id / payload_json — the payload snapshot carries record titles, so business names match with no join.
  • Page window pushdown: limit/offset push into the engine (orderBy created_at desc) whenever the filter is fully pushable. approverId / status-array filters still post-filter their bounded scan and window in memory — correct for personal queues; the org-wide approver case is the documented residual until the approver join-table follow-up (perf(approvals): server-side pagination + pushdown filtering for listRequests #1745 stays open for that).
  • countRequests: unwindowed total via engine count() when pushable, bounded scan otherwise.
  • REST: GET /approvals/requests accepts q/limit/offset, returns {data, total} when paging; unpaged callers keep the old shape (no extra count query).

Test plan

  • plugin-approvals: 64 tests (4 new: window newest-first/no-overlap, q matches payload titles, count totals, approver in-memory windowing after exact-match filter) ✅ — fake engine extended with $or/$contains/offset
  • Live e2e on showcase: limit=10&offset=0/10 pages with zero overlap and total=31; q=Compliance → 5/5 matches; status=recalled → 2/2. Console: 56 rows → first page 50 + 「加载更多」 → 56/56 with the button gone; a debounced UI search for a title on an unloaded page returned the row (server search, not page filtering) ✅

🤖 Generated with Claude Code

…uests

Closes the dangerous half of #1745: beyond the 500-row scan cap the
inbox silently lost rows. listRequests gains q/limit/offset:

- Free-text q pushes into the engine query as an $or of $contains
  terms over process_name / object_name / record_id / submitter_id /
  payload_json — the payload snapshot carries record titles, so titles
  match with no join and no enrichment round-trip.
- The page window pushes into the engine (orderBy created_at desc)
  whenever the filter is fully pushable. approverId / status-array
  filters still post-filter in memory over the bounded scan and window
  after filtering — correct for personal queues, and the documented
  residual limit until the approver join-table follow-up (#1745).
- New countRequests returns the unwindowed total, using engine count()
  when pushable and the bounded scan otherwise.
- REST: GET /approvals/requests accepts q/limit/offset and returns
  {data, total} when paging (total costs a second query, so unpaged
  callers keep the old shape).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@os-zhuang
os-zhuang merged commit 11d9ece into main Jun 12, 2026
1 of 2 checks passed
@os-zhuang
os-zhuang deleted the feat-approvals-server-pagination branch June 12, 2026 05:25
@vercel

vercel Bot commented Jun 12, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
spec Building Building Preview, Comment Jun 12, 2026 5:25am

Request Review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant