Decouple stats from tree endpoint response

This commit is contained in:
Sebastian Martinez
2024-05-02 23:58:44 +02:00
parent eef0c1b0c7
commit 70b16e5861
8 changed files with 71 additions and 30 deletions
+2
View File
@@ -6,6 +6,7 @@ import type {
ProjectListQuery,
Remote,
Tree,
TreeStats,
} from "./lib/project.js";
import type {
SuccessResponse,
@@ -82,6 +83,7 @@ export type {
Review,
Revision,
Scope,
TreeStats,
Tree,
Verdict,
};
+30 -10
View File
@@ -102,11 +102,13 @@ const treeEntrySchema = object({
export type TreeEntry = z.infer<typeof treeEntrySchema>;
export interface TreeStats {
commits: number;
branches: number;
contributors: number;
}
const treeStatsSchema = object({
commits: number(),
branches: number(),
contributors: number(),
});
export type TreeStats = z.infer<typeof treeStatsSchema>;
export type Tree = z.infer<typeof treeSchema>;
@@ -115,11 +117,6 @@ const treeSchema = object({
lastCommit: commitHeaderSchema,
name: string(),
path: string(),
stats: object({
commits: number(),
branches: number(),
contributors: number(),
}),
});
export type Remote = z.infer<typeof remoteSchema>;
@@ -153,6 +150,7 @@ export class Client {
// persisted and new instances are frequently created.
static #cache = {
tree: new LRUCache<string, Tree>({ max: 300 }),
stats: new LRUCache<string, TreeStats>({ max: 300 }),
blob: new LRUCache<string, Blob>({ max: 500 }),
};
@@ -275,6 +273,28 @@ export class Client {
return tree;
}
public async getTreeStatsBySha(
id: string,
sha: string,
options?: RequestOptions,
): Promise<TreeStats> {
const cacheKey = `tree:stats:${sha}`;
const cachedTree = Client.#cache.stats.get(cacheKey);
if (cachedTree) {
return cachedTree;
}
const tree = await this.#fetcher.fetchOk(
{
method: "GET",
path: `projects/${id}/stats/tree/${sha}`,
options,
},
treeStatsSchema,
);
Client.#cache.stats.set(cacheKey, tree);
return tree;
}
public async getAllRemotes(
id: string,
options?: RequestOptions,
+1 -8
View File
@@ -236,11 +236,4 @@ const commitSchema = object({
type Commits = z.infer<typeof commitsSchema>;
const commitsSchema = object({
commits: array(commitHeaderSchema),
stats: object({
commits: number(),
branches: number(),
contributors: number(),
}),
});
const commitsSchema = array(commitHeaderSchema);
+4
View File
@@ -53,6 +53,10 @@ describe("project", () => {
await api.project.getTree(sourceBrowsingRid, aliceMainHead);
});
test("#getTreeStats(id, sha)", async () => {
await api.project.getTreeStatsBySha(sourceBrowsingRid, aliceMainHead);
});
test("#getTree(id, sha, path)", async () => {
await api.project.getTree(sourceBrowsingRid, aliceMainHead, "src");
});
+6 -5
View File
@@ -5,6 +5,7 @@
Project,
Remote,
Tree,
TreeStats,
} from "@httpd-client";
import type { Route } from "@app/lib/router";
@@ -29,8 +30,8 @@
export let peers: Remote[];
export let project: Project;
export let revision: string | undefined;
export let totalCommitCount: number;
export let tree: Tree;
export let stats: TreeStats;
export let seeding: boolean;
const api = new HttpdClient(baseUrl);
@@ -54,8 +55,7 @@
page,
perPage: COMMITS_PER_PAGE,
});
allCommitHeaders = response.commits;
totalCommitCount = response.stats.commits;
allCommitHeaders = response;
} catch (e) {
error = e;
}
@@ -117,6 +117,7 @@
branches={branchesWithRoute}
{revision}
{tree}
{stats}
filesLinkActive={false}
historyLinkActive={true} />
</div>
@@ -135,11 +136,11 @@
{/each}
</div>
{#if loading || allCommitHeaders.length < totalCommitCount}
{#if loading || allCommitHeaders.length < stats.commits}
<div class="more">
{#if loading}
<Loading small={page !== 0} center />
{:else if allCommitHeaders.length < totalCommitCount}
{:else if allCommitHeaders.length < stats.commits}
<Button size="large" variant="outline" on:click={loadMore}>More</Button>
{/if}
</div>
+9 -1
View File
@@ -1,5 +1,11 @@
<script lang="ts">
import type { BaseUrl, Project, Remote, Tree } from "@httpd-client";
import type {
BaseUrl,
Project,
Remote,
Tree,
TreeStats,
} from "@httpd-client";
import type { BlobResult } from "./router";
import type { Route } from "@app/lib/router";
@@ -24,6 +30,7 @@
export let project: Project;
export let revision: string | undefined;
export let tree: Tree;
export let stats: TreeStats;
export let seeding: boolean;
let mobileFileTree = false;
@@ -125,6 +132,7 @@
branches={branchesWithRoute}
{revision}
{tree}
{stats}
filesLinkActive={true}
historyLinkActive={false} />
</div>
+9 -2
View File
@@ -1,5 +1,11 @@
<script lang="ts">
import type { BaseUrl, Project, Remote, Tree } from "@httpd-client";
import type {
BaseUrl,
Project,
Remote,
Tree,
TreeStats,
} from "@httpd-client";
import { type Route } from "@app/lib/router";
import BranchSelector from "./BranchSelector.svelte";
@@ -16,6 +22,7 @@
export let historyLinkActive: boolean;
export let revision: string | undefined;
export let tree: Tree;
export let stats: TreeStats;
export let project: Project;
let selectedBranch: string | undefined;
@@ -121,7 +128,7 @@
<div class="title-counter">
Commits
<div class="counter" class:selected={historyLinkActive}>
{tree.stats.commits}
{stats.commits}
</div>
</div>
</Button>
+10 -4
View File
@@ -18,6 +18,7 @@ import type {
Project,
Remote,
Tree,
TreeStats,
} from "@httpd-client";
import * as Syntax from "@app/lib/syntax";
@@ -117,6 +118,7 @@ export type ProjectLoadedRoute =
branches: string[];
revision: string | undefined;
tree: Tree;
stats: TreeStats;
path: string;
rawPath: (commit?: string) => string;
blobResult: BlobResult;
@@ -133,8 +135,8 @@ export type ProjectLoadedRoute =
branches: string[];
revision: string | undefined;
tree: Tree;
stats: TreeStats;
commitHeaders: CommitHeader[];
totalCommitCount: number;
seeding: boolean;
};
}
@@ -443,6 +445,8 @@ async function loadTreeView(
branchMap,
);
const stats = await api.project.getTreeStatsBySha(route.project, commit);
const path = route.path || "/";
const [tree, blobResult] = await Promise.all([
@@ -460,6 +464,7 @@ async function loadTreeView(
rawPath,
revision: route.revision,
tree,
stats,
path,
blobResult,
seeding,
@@ -533,8 +538,9 @@ async function loadHistoryView(
);
}
const [tree, commitsResponse, seeding] = await Promise.all([
const [tree, stats, commitHeaders, seeding] = await Promise.all([
api.project.getTree(route.project, commitId),
api.project.getTreeStatsBySha(route.project, commitId),
await api.project.getAllCommits(project.id, {
parent: commitId,
page: 0,
@@ -553,8 +559,8 @@ async function loadHistoryView(
branches: Object.keys(branchMap || {}),
revision: route.revision,
tree,
commitHeaders: commitsResponse.commits,
totalCommitCount: commitsResponse.stats.commits,
stats,
commitHeaders,
seeding,
},
};