Watch
0
0
Fork
You've already forked hyperhive
0

hive-forge: fetch issue comments in one request; the endpoint has no paging

The forge's issue-comments endpoint takes no page or limit and always
returns the whole thread. #5055 wrapped view's fetch in all_pages, which
never saw a short page on a thread of 50+ comments and fetched the same
list 50 times: `issue view 3782` printed 3000 comments instead of 60.
`comments --limit K` sent K as a page size the forge ignored, so it
returned the whole thread.

view and pr status's last_comment now send one request. comments fetches
the thread once and cuts the --limit / --tail window client-side; the
X-Total-Count probe and the computed-page tail walk are gone, and the
count of comments outside the window is the length of the list.
--since is unchanged.

tests/comments_no_paging.rs runs the binary against a loopback mock
forge whose comments route ignores page and limit, as Forgejo's does.
This commit is contained in:
atlas 2026-10-09 21:04:40 +02:00
commit 1d56a74aad

View file

@ -213,35 +213,24 @@ fn fetch_combined(client: &Client, sha: &str) -> Result<(String, Vec<Value>)> {
}
/// The most recent issue comment on the PR, as `(login, created_at)`.
/// Comments page oldest-first; we drain (bounded) and take the max
/// timestamp so a long thread still reports the genuinely-latest one.
/// One request: the comments endpoint takes no page or limit and returns
/// the whole thread. Takes the max timestamp rather than the last row.
fn last_comment(client: &Client, pr: u64) -> Result<Option<(String, String)>> {
const PAGE_SIZE: u32 = 50;
const MAX_PAGES: u32 = 20;
let (owner, name) = client.owner_repo()?;
let idx = index(pr)?;
let (_, comments) = client
.api()
.issue_get_comments(owner, name, index(pr)?, IssueGetCommentsQuery::default())
.send()?;
let mut last: Option<(String, String)> = None;
for page in 1..=MAX_PAGES {
let (_, comments) = client
.api()
.issue_get_comments(owner, name, idx, IssueGetCommentsQuery::default())
.page(page)
.page_size(PAGE_SIZE)
.send()?;
let short = comments.len() < PAGE_SIZE as usize;
for c in &comments {
let Some(login) = c.user.as_ref().and_then(|u| u.login.clone()) else {
continue;
};
let Some(created) = rfc3339(c.created_at) else {
continue;
};
if last.as_ref().is_none_or(|(_, t)| created > *t) {
last = Some((login, created));
}
}
if short {
break;
for c in &comments {
let Some(login) = c.user.as_ref().and_then(|u| u.login.clone()) else {
continue;
};
let Some(created) = rfc3339(c.created_at) else {
continue;
};
if last.as_ref().is_none_or(|(_, t)| created > *t) {
last = Some((login, created));
}
}
Ok(last)