Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/search-cursor-pagination.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@hyperdx/api': minor
'@hyperdx/common-utils': patch
---

Add cursor pagination to the external API v2 search endpoint: send `cursor: "start"`, then pass back each `nextCursor` until it is `null`. Cursors are signed with `EXPRESS_SESSION_SECRET`: replicas need a shared value, and rotating it invalidates outstanding cursors.
14 changes: 13 additions & 1 deletion packages/api/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -4812,7 +4812,13 @@
"minimum": 0,
"maximum": 10000,
"default": 0,
"description": "Number of rows to skip (best-effort offset pagination). Default is\n0, max is 10000. Offset pagination is non-deterministic when\nmultiple rows share the same timestamp; for reliable deep paging\nfilter by the last Timestamp value returned in the previous page\ninstead of using a large offset.\n"
"description": "Number of rows to skip (best-effort offset pagination). Default is\n0, max is 10000. Offset pagination is non-deterministic when\nmultiple rows share the same timestamp. Prefer cursor for paging.\n"
},
"cursor": {
"type": "string",
"maxLength": 1024,
"example": "start",
"description": "Send the literal string \"start\" to begin cursor paging, then pass\nback the nextCursor from each response. When set, offset is\nignored; omit cursor entirely to use offset-based paging.\nAs with offset, rows that share a timestamp can be skipped or\nrepeated between pages unless orderBy breaks the tie.\n\nKeep requesting pages until nextCursor is null. A page that is\nempty or returns fewer rows than maxResults does NOT mean the\nresults are exhausted.\n"
}
}
},
Expand All @@ -4834,6 +4840,12 @@
"rows": {
"type": "integer",
"description": "Number of rows in this response (not total matching rows)."
},
"nextCursor": {
"type": "string",
"nullable": true,
"example": "eyJ2IjoxLCJ3IjoyLCJvIjo1MDAsImYiOiJhMWIyYzNkNGU1ZjZhN2I4In0",
"description": "Cursor for the next page, or null when the walk is complete or the request did not include a cursor. Pass it back as cursor in the next request to fetch the next page. This is an opaque value; no guarantees are made about its content.\n"
}
}
},
Expand Down
Loading
Loading