mirror of
https://github.com/sourcebot-dev/sourcebot.git
synced 2025-12-12 04:15:30 +00:00
fix(perf): Add indices to hot paths for repository querying (#526)
This commit is contained in:
parent
5dcc538878
commit
5bc8fc323a
6 changed files with 106 additions and 0 deletions
|
|
@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Improved repository query performance by adding db indices. [#526](https://github.com/sourcebot-dev/sourcebot/pull/526)
|
||||||
|
|
||||||
## [4.7.1] - 2025-09-19
|
## [4.7.1] - 2025-09-19
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE INDEX "Repo_orgId_idx" ON "Repo"("orgId");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE INDEX "RepoToConnection_repoId_connectionId_idx" ON "RepoToConnection"("repoId", "connectionId");
|
||||||
|
|
@ -71,6 +71,7 @@ model Repo {
|
||||||
searchContexts SearchContext[]
|
searchContexts SearchContext[]
|
||||||
|
|
||||||
@@unique([external_id, external_codeHostUrl, orgId])
|
@@unique([external_id, external_codeHostUrl, orgId])
|
||||||
|
@@index([orgId])
|
||||||
}
|
}
|
||||||
|
|
||||||
model SearchContext {
|
model SearchContext {
|
||||||
|
|
@ -119,6 +120,7 @@ model RepoToConnection {
|
||||||
repoId Int
|
repoId Int
|
||||||
|
|
||||||
@@id([connectionId, repoId])
|
@@id([connectionId, repoId])
|
||||||
|
@@index([repoId, connectionId])
|
||||||
}
|
}
|
||||||
|
|
||||||
model Invite {
|
model Invite {
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@ import { migrateDuplicateConnections } from "./scripts/migrate-duplicate-connect
|
||||||
import { injectAuditData } from "./scripts/inject-audit-data";
|
import { injectAuditData } from "./scripts/inject-audit-data";
|
||||||
import { confirmAction } from "./utils";
|
import { confirmAction } from "./utils";
|
||||||
import { createLogger } from "@sourcebot/logger";
|
import { createLogger } from "@sourcebot/logger";
|
||||||
|
import { injectRepoData } from "./scripts/inject-repo-data";
|
||||||
|
import { testRepoQueryPerf } from "./scripts/test-repo-query-perf";
|
||||||
|
|
||||||
export interface Script {
|
export interface Script {
|
||||||
run: (prisma: PrismaClient) => Promise<void>;
|
run: (prisma: PrismaClient) => Promise<void>;
|
||||||
|
|
@ -12,6 +14,8 @@ export interface Script {
|
||||||
export const scripts: Record<string, Script> = {
|
export const scripts: Record<string, Script> = {
|
||||||
"migrate-duplicate-connections": migrateDuplicateConnections,
|
"migrate-duplicate-connections": migrateDuplicateConnections,
|
||||||
"inject-audit-data": injectAuditData,
|
"inject-audit-data": injectAuditData,
|
||||||
|
"inject-repo-data": injectRepoData,
|
||||||
|
"test-repo-query-perf": testRepoQueryPerf,
|
||||||
}
|
}
|
||||||
|
|
||||||
const parser = new ArgumentParser();
|
const parser = new ArgumentParser();
|
||||||
|
|
|
||||||
64
packages/db/tools/scripts/inject-repo-data.ts
Normal file
64
packages/db/tools/scripts/inject-repo-data.ts
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
import { Script } from "../scriptRunner";
|
||||||
|
import { PrismaClient } from "../../dist";
|
||||||
|
import { createLogger } from "@sourcebot/logger";
|
||||||
|
|
||||||
|
const logger = createLogger('inject-repo-data');
|
||||||
|
|
||||||
|
const NUM_REPOS = 100000;
|
||||||
|
|
||||||
|
export const injectRepoData: Script = {
|
||||||
|
run: async (prisma: PrismaClient) => {
|
||||||
|
const orgId = 1;
|
||||||
|
|
||||||
|
// Check if org exists
|
||||||
|
const org = await prisma.org.findUnique({
|
||||||
|
where: { id: orgId }
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!org) {
|
||||||
|
await prisma.org.create({
|
||||||
|
data: {
|
||||||
|
id: orgId,
|
||||||
|
name: 'Test Org',
|
||||||
|
domain: 'test-org.com'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const connection = await prisma.connection.create({
|
||||||
|
data: {
|
||||||
|
orgId,
|
||||||
|
name: 'test-connection',
|
||||||
|
connectionType: 'github',
|
||||||
|
config: {}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
logger.info(`Creating ${NUM_REPOS} repos...`);
|
||||||
|
|
||||||
|
for (let i = 0; i < NUM_REPOS; i++) {
|
||||||
|
await prisma.repo.create({
|
||||||
|
data: {
|
||||||
|
name: `test-repo-${i}`,
|
||||||
|
isFork: false,
|
||||||
|
isArchived: false,
|
||||||
|
metadata: {},
|
||||||
|
cloneUrl: `https://github.com/test-org/test-repo-${i}`,
|
||||||
|
webUrl: `https://github.com/test-org/test-repo-${i}`,
|
||||||
|
orgId,
|
||||||
|
external_id: `test-repo-${i}`,
|
||||||
|
external_codeHostType: 'github',
|
||||||
|
external_codeHostUrl: 'https://github.com',
|
||||||
|
connections: {
|
||||||
|
create: {
|
||||||
|
connectionId: connection.id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info(`Created ${NUM_REPOS} repos.`);
|
||||||
|
}
|
||||||
|
};
|
||||||
28
packages/db/tools/scripts/test-repo-query-perf.ts
Normal file
28
packages/db/tools/scripts/test-repo-query-perf.ts
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
import { Script } from "../scriptRunner";
|
||||||
|
import { PrismaClient } from "../../dist";
|
||||||
|
import { createLogger } from "@sourcebot/logger";
|
||||||
|
|
||||||
|
const logger = createLogger('test-repo-query-perf');
|
||||||
|
|
||||||
|
export const testRepoQueryPerf: Script = {
|
||||||
|
run: async (prisma: PrismaClient) => {
|
||||||
|
|
||||||
|
|
||||||
|
const start = Date.now();
|
||||||
|
const allRepos = await prisma.repo.findMany({
|
||||||
|
where: {
|
||||||
|
orgId: 1,
|
||||||
|
},
|
||||||
|
include: {
|
||||||
|
connections: {
|
||||||
|
include: {
|
||||||
|
connection: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const durationMs = Date.now() - start;
|
||||||
|
logger.info(`Found ${allRepos.length} repos in ${durationMs}ms`);
|
||||||
|
}
|
||||||
|
};
|
||||||
Loading…
Reference in a new issue