(tag, pageFn, log, maxPages = 50)
| 1225 | // Paginated helper that walks all pages of a list endpoint with retry and |
| 1226 | // pacing. Returns the concatenated array of items. |
| 1227 | async function readAllPages(tag, pageFn, log, maxPages = 50) { |
| 1228 | if (!Number.isFinite(maxPages) || maxPages < 1) { |
| 1229 | throw new Error(`readAllPages: maxPages must be a positive integer, got ${maxPages}`); |
| 1230 | } |
| 1231 | const all = []; |
| 1232 | let page = 1; |
| 1233 | const PER_PAGE = 100; |
| 1234 | while (page <= maxPages) { |
| 1235 | const res = await readWithPacing(`${tag} (page ${page})`, () => pageFn(page, PER_PAGE), log); |
| 1236 | const items = res.data || []; |
| 1237 | all.push(...items); |
| 1238 | if (items.length < PER_PAGE) break; |
| 1239 | page++; |
| 1240 | } |
| 1241 | // NOTE: Truncation here is intentional and acts as a safety valve against |
| 1242 | // unbounded loops (e.g. a bug or malicious activity), not as a normal |
| 1243 | // operating mode. A PR accumulating >5000 review comments is far outside |
| 1244 | // expected usage; in that rare case we log a warning and proceed with |
| 1245 | // partial data rather than failing the whole review. |
| 1246 | // |
| 1247 | // Caveat: this is NOT the same as a read failure. When the read API throws |
| 1248 | // (rate limit, 5xx), isCommentAlreadyPosted catches it and returns null |
| 1249 | // (unknown), so the caller skips retrying and creates no duplicate. A |
| 1250 | // truncated walk does not throw; it returns a partial set silently, so |
| 1251 | // isCommentAlreadyPosted returns false (definitively "not posted") for any |
| 1252 | // comment beyond the cap, and the retry loop will repost it, producing a |
| 1253 | // duplicate. This tradeoff is accepted because the trigger is far outside |
| 1254 | // expected usage; if that ceiling ever needs to rise, make maxPages |
| 1255 | // configurable. |
| 1256 | if (page > maxPages) { |
| 1257 | log(`[${tag}] reached max page limit (${maxPages}); results may be incomplete.`); |
| 1258 | } |
| 1259 | return all; |
| 1260 | } |
| 1261 | |
| 1262 | // Idempotency check: find whether a batch review with this run tag already |
| 1263 | // exists on the PR. Returns { found, review } or throws on final failure |
no test coverage detected