mirror of
https://gitbruv.vercel.app/api/git/bruv/gitbruv.git
synced 2025-12-20 23:24:09 +01:00
caching
This commit is contained in:
parent
d589bad9d5
commit
bdcdfc7450
2 changed files with 48 additions and 34 deletions
|
|
@ -4,7 +4,7 @@ import { db } from "@/db";
|
||||||
import { repositories, users, stars } from "@/db/schema";
|
import { repositories, users, stars } from "@/db/schema";
|
||||||
import { getSession } from "@/lib/session";
|
import { getSession } from "@/lib/session";
|
||||||
import { eq, and, desc, count, sql } from "drizzle-orm";
|
import { eq, and, desc, count, sql } from "drizzle-orm";
|
||||||
import { revalidatePath } from "next/cache";
|
import { revalidatePath, unstable_cache } from "next/cache";
|
||||||
import git from "isomorphic-git";
|
import git from "isomorphic-git";
|
||||||
import { createR2Fs, getRepoPrefix } from "@/lib/r2-fs";
|
import { createR2Fs, getRepoPrefix } from "@/lib/r2-fs";
|
||||||
|
|
||||||
|
|
@ -560,31 +560,8 @@ export type FileEntry = {
|
||||||
lastCommit: { message: string; timestamp: number } | null;
|
lastCommit: { message: string; timestamp: number } | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export async function getRepoPageData(owner: string, repoName: string) {
|
async function fetchGitData(userId: string, repoName: string, defaultBranch: string) {
|
||||||
const [user, session] = await Promise.all([db.query.users.findFirst({ where: eq(users.username, owner) }), getSession()]);
|
const repoPrefix = getRepoPrefix(userId, `${repoName}.git`);
|
||||||
|
|
||||||
if (!user) return null;
|
|
||||||
|
|
||||||
const repo = await db.query.repositories.findFirst({
|
|
||||||
where: and(eq(repositories.ownerId, user.id), eq(repositories.name, repoName)),
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!repo) return null;
|
|
||||||
|
|
||||||
if (repo.visibility === "private" && (!session?.user || session.user.id !== repo.ownerId)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const [starCountResult, starredResult] = await Promise.all([
|
|
||||||
db.select({ count: count() }).from(stars).where(eq(stars.repositoryId, repo.id)),
|
|
||||||
session?.user ? db.query.stars.findFirst({ where: and(eq(stars.userId, session.user.id), eq(stars.repositoryId, repo.id)) }) : Promise.resolve(null),
|
|
||||||
]);
|
|
||||||
|
|
||||||
const starCount = starCountResult[0]?.count ?? 0;
|
|
||||||
const starred = !!starredResult;
|
|
||||||
const isOwner = session?.user?.id === repo.ownerId;
|
|
||||||
|
|
||||||
const repoPrefix = getRepoPrefix(user.id, `${repoName}.git`);
|
|
||||||
const fs = createR2Fs(repoPrefix);
|
const fs = createR2Fs(repoPrefix);
|
||||||
|
|
||||||
let files: FileEntry[] = [];
|
let files: FileEntry[] = [];
|
||||||
|
|
@ -594,7 +571,7 @@ export async function getRepoPageData(owner: string, repoName: string) {
|
||||||
let commitCount = 0;
|
let commitCount = 0;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const [branchList, commits] = await Promise.all([git.listBranches({ fs, gitdir: "/" }), git.log({ fs, gitdir: "/", ref: repo.defaultBranch })]);
|
const [branchList, commits] = await Promise.all([git.listBranches({ fs, gitdir: "/" }), git.log({ fs, gitdir: "/", ref: defaultBranch })]);
|
||||||
|
|
||||||
branches = branchList;
|
branches = branchList;
|
||||||
commitCount = commits.length;
|
commitCount = commits.length;
|
||||||
|
|
@ -609,7 +586,7 @@ export async function getRepoPageData(owner: string, repoName: string) {
|
||||||
tree.map(async (entry) => {
|
tree.map(async (entry) => {
|
||||||
let lastCommit: { message: string; timestamp: number } | null = null;
|
let lastCommit: { message: string; timestamp: number } | null = null;
|
||||||
try {
|
try {
|
||||||
const fileCommits = await git.log({ fs, gitdir: "/", ref: repo.defaultBranch, filepath: entry.path, depth: 1 });
|
const fileCommits = await git.log({ fs, gitdir: "/", ref: defaultBranch, filepath: entry.path, depth: 1 });
|
||||||
if (fileCommits.length > 0) {
|
if (fileCommits.length > 0) {
|
||||||
lastCommit = {
|
lastCommit = {
|
||||||
message: fileCommits[0].commit.message.split("\n")[0],
|
message: fileCommits[0].commit.message.split("\n")[0],
|
||||||
|
|
@ -644,10 +621,44 @@ export async function getRepoPageData(owner: string, repoName: string) {
|
||||||
} catch (err: unknown) {
|
} catch (err: unknown) {
|
||||||
const error = err as { code?: string };
|
const error = err as { code?: string };
|
||||||
if (error.code !== "NotFoundError") {
|
if (error.code !== "NotFoundError") {
|
||||||
console.error("getRepoPageData error:", err);
|
console.error("fetchGitData error:", err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return { files, isEmpty, readmeContent, branches, commitCount };
|
||||||
|
}
|
||||||
|
|
||||||
|
const getCachedGitData = (owner: string, repoName: string, userId: string, defaultBranch: string) =>
|
||||||
|
unstable_cache(() => fetchGitData(userId, repoName, defaultBranch), [`git-data`, owner, repoName], {
|
||||||
|
tags: [`repo:${owner}/${repoName}`],
|
||||||
|
revalidate: 3600,
|
||||||
|
})();
|
||||||
|
|
||||||
|
export async function getRepoPageData(owner: string, repoName: string) {
|
||||||
|
const [user, session] = await Promise.all([db.query.users.findFirst({ where: eq(users.username, owner) }), getSession()]);
|
||||||
|
|
||||||
|
if (!user) return null;
|
||||||
|
|
||||||
|
const repo = await db.query.repositories.findFirst({
|
||||||
|
where: and(eq(repositories.ownerId, user.id), eq(repositories.name, repoName)),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!repo) return null;
|
||||||
|
|
||||||
|
if (repo.visibility === "private" && (!session?.user || session.user.id !== repo.ownerId)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const [starCountResult, starredResult, gitData] = await Promise.all([
|
||||||
|
db.select({ count: count() }).from(stars).where(eq(stars.repositoryId, repo.id)),
|
||||||
|
session?.user ? db.query.stars.findFirst({ where: and(eq(stars.userId, session.user.id), eq(stars.repositoryId, repo.id)) }) : Promise.resolve(null),
|
||||||
|
getCachedGitData(owner, repoName, user.id, repo.defaultBranch),
|
||||||
|
]);
|
||||||
|
|
||||||
|
const starCount = starCountResult[0]?.count ?? 0;
|
||||||
|
const starred = !!starredResult;
|
||||||
|
const isOwner = session?.user?.id === repo.ownerId;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
repo: {
|
repo: {
|
||||||
...repo,
|
...repo,
|
||||||
|
|
@ -655,11 +666,11 @@ export async function getRepoPageData(owner: string, repoName: string) {
|
||||||
starCount,
|
starCount,
|
||||||
starred,
|
starred,
|
||||||
},
|
},
|
||||||
files,
|
...gitData,
|
||||||
isEmpty,
|
|
||||||
readmeContent,
|
|
||||||
branches,
|
|
||||||
commitCount,
|
|
||||||
isOwner,
|
isOwner,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getRepoCacheTag(owner: string, repoName: string) {
|
||||||
|
return `repo:${owner}/${repoName}`;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,8 @@ import git from "isomorphic-git";
|
||||||
import { createR2Fs, getRepoPrefix } from "@/lib/r2-fs";
|
import { createR2Fs, getRepoPrefix } from "@/lib/r2-fs";
|
||||||
import { scryptAsync } from "@noble/hashes/scrypt.js";
|
import { scryptAsync } from "@noble/hashes/scrypt.js";
|
||||||
import { hexToBytes } from "@noble/hashes/utils.js";
|
import { hexToBytes } from "@noble/hashes/utils.js";
|
||||||
|
import { revalidateTag } from "next/cache";
|
||||||
|
import { getRepoCacheTag } from "@/actions/repositories";
|
||||||
|
|
||||||
function constantTimeEqual(a: Uint8Array, b: Uint8Array): boolean {
|
function constantTimeEqual(a: Uint8Array, b: Uint8Array): boolean {
|
||||||
if (a.length !== b.length) return false;
|
if (a.length !== b.length) return false;
|
||||||
|
|
@ -437,6 +439,7 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{
|
||||||
response = await handleUploadPack(fs, "/", body);
|
response = await handleUploadPack(fs, "/", body);
|
||||||
} else {
|
} else {
|
||||||
response = await handleReceivePack(fs, "/", body);
|
response = await handleReceivePack(fs, "/", body);
|
||||||
|
revalidateTag(getRepoCacheTag(username, repoName), { expire: 0 });
|
||||||
}
|
}
|
||||||
|
|
||||||
return new NextResponse(new Uint8Array(response), {
|
return new NextResponse(new Uint8Array(response), {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue