Skip to content

Commit

Events of one type are read by repository and type, and the home page reads a short page of pushes and history first (events 0007)

syntaqxcommitted Parent27b8487Browse files
4 files+49−50/4 viewed
+17−0
44 import {
55 type Merged,
66 placePushes,
7+ historyCovers,
78 change,
89 checksFact,
910 confidenceAsk,
204205 assert.deepEqual(placePushes(history, pushes), [{ hash: "m1", at: "2026-10-05T12:00:00Z" }]);
205206 });
206207
208+test("a short read of the branch is enough when it reaches the oldest push", () => {
209+ const h = (...hashes: string[]) => hashes.map((hash) => ({ hash }));
210+ const pushes = [
211+ { time: "2026-10-07T12:00:00Z", data: { after: "c1", before: "c2" } },
212+ { time: "2026-10-05T12:00:00Z", data: { after: "c2", before: "c3" } },
213+ ];
214+ // Holds the oldest push's before.
215+ assert.ok(historyCovers(h("c1", "c2", "c3"), pushes, 3));
216+ // Full, and the oldest push reaches past it: read further.
217+ assert.ok(!historyCovers(h("c1", "c2", "x"), pushes, 3));
218+ // Shorter than asked: the whole branch.
219+ assert.ok(historyCovers(h("c1", "c2"), pushes, 3));
220+ // The oldest push made the branch: only the whole branch will do.
221+ assert.ok(!historyCovers(h("c1", "c2", "c3"), [{ time: "", data: { after: "c1" } }], 3));
222+});
223+
207224 test("a change landed without a person when g1t merged it", () => {
208225 assert.ok(landedByAgents({ mergedBy: "g1t" }));
209226 assert.ok(landedByAgents({ mergedBy: "g1t" }));
+11−0
503503 return [...seen].flatMap(([hash, at]) => (at ? [{ hash, at }] : []));
504504 }
505505
506+/**
507+ * Whether a read of the default branch reaches back far enough to place
508+ * every push, newest first: it holds the oldest push's `before`, or it is
509+ * the whole branch. A shorter read than `asked` is the whole branch.
510+ */
511+export function historyCovers(history: { hash: string }[], pushes: PushRecord[], asked: number): boolean {
512+ if (history.length < asked) return true;
513+ const oldest = pushes.at(-1)?.data.before;
514+ return oldest != null && history.some((commit) => commit.hash === oldest);
515+}
516+
506517 /** A merged pull request, as the week counts it. */
507518 export type Merged = {
508519 repo: RepoPath;
+16−5
5757 usd,
5858 waitingRows,
5959 weekOf,
60+ historyCovers,
6061 who,
6162 whyFor,
6263 withConfidence,
161162 */
162163 const PUSH_PAGE = 200;
163164 const PUSH_PAGES = 5;
164−/** Commits of the default branch read once, to place each push's commits. */
165+/** The first page is smaller: most projects push far less in two weeks. */
166+const FIRST_PUSH_PAGE = 50;
167+/**
168+ * Commits of the default branch read to place each push's commits: a
169+ * short read first, which covers most projects' fortnight, and the longer
170+ * one only when it does not reach the oldest push.
171+ */
172+const HISTORY_FIRST = 200;
165173 const HISTORY_READ = 1000;
166174
167175 /**
174182 const pushes: G1tEvent<"git.push">[] = [];
175183 let before: string | undefined;
176184 for (let page = 0; page < PUSH_PAGES; page++) {
177− const batch = await eventLog.list({ repoId: repo.id, types: ["git.push"], limit: PUSH_PAGE, ...(before ? { before } : {}) });
185+ const limit = page === 0 ? FIRST_PUSH_PAGE : PUSH_PAGE;
186+ const batch = await eventLog.list({ repoId: repo.id, types: ["git.push"], limit, ...(before ? { before } : {}) });
178187 for (const event of batch) {
179188 if (event.type === "git.push" && event.data.defaultBranch && Date.parse(event.time) >= since) pushes.push(event as G1tEvent<"git.push">);
180189 }
181190 const oldest = batch.at(-1);
182− if (batch.length < PUSH_PAGE || !oldest || Date.parse(oldest.time) < since) break;
191+ if (batch.length < limit || !oldest || Date.parse(oldest.time) < since) break;
183192 before = oldest.id;
184193 }
185194 if (pushes.length === 0) return [];
186− // One read of the branch from the newest push back; each push brought
195+ // A read of the branch from the newest push back; each push brought
187196 // what lies between its `after` and its `before` in that history.
188197 const path = { namespace: repo.namespace, name: repo.name };
189− const history = await reposApi.log(path, viewer, pushes[0].data.after, HISTORY_READ).catch(() => null);
198+ const read = (limit: number) => reposApi.log(path, viewer, pushes[0].data.after, limit).catch(() => null);
199+ let history = await read(HISTORY_FIRST);
200+ if (history?.ok && !historyCovers(history.value, pushes, HISTORY_FIRST)) history = await read(HISTORY_READ);
190201 if (!history?.ok) return [];
191202 // g1t's own commits are told by their author address, never by name.
192203 return placePushes(history.value, pushes, (commit) => G1T_COMMIT_EMAILS.has(normalizeEmail(commit.author.email)));
+5−0
1+-- A repository's events of some types, newest first: the home page's pushes,
2+-- the overview's feed and the Activity tab. By repository, type and id
3+-- those are ranges, rather than a walk back through every event the
4+-- repository ever had.
5+CREATE INDEX IF NOT EXISTS events_repo_type ON events (repo_id, type, id);