Skip to content

Commit 5bc8fc3

Browse files
fix(perf): Add indices to hot paths for repository querying (#526)
1 parent 5dcc538 commit 5bc8fc3

File tree

6 files changed

+106
-0
lines changed

6 files changed

+106
-0
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Changed
11+
- Improved repository query performance by adding db indices. [#526](https://github.com/sourcebot-dev/sourcebot/pull/526)
12+
1013
## [4.7.1] - 2025-09-19
1114

1215
### Fixed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
-- CreateIndex
2+
CREATE INDEX "Repo_orgId_idx" ON "Repo"("orgId");
3+
4+
-- CreateIndex
5+
CREATE INDEX "RepoToConnection_repoId_connectionId_idx" ON "RepoToConnection"("repoId", "connectionId");

packages/db/prisma/schema.prisma

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ model Repo {
7171
searchContexts SearchContext[]
7272
7373
@@unique([external_id, external_codeHostUrl, orgId])
74+
@@index([orgId])
7475
}
7576

7677
model SearchContext {
@@ -119,6 +120,7 @@ model RepoToConnection {
119120
repoId Int
120121
121122
@@id([connectionId, repoId])
123+
@@index([repoId, connectionId])
122124
}
123125

124126
model Invite {

packages/db/tools/scriptRunner.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import { migrateDuplicateConnections } from "./scripts/migrate-duplicate-connect
44
import { injectAuditData } from "./scripts/inject-audit-data";
55
import { confirmAction } from "./utils";
66
import { createLogger } from "@sourcebot/logger";
7+
import { injectRepoData } from "./scripts/inject-repo-data";
8+
import { testRepoQueryPerf } from "./scripts/test-repo-query-perf";
79

810
export interface Script {
911
run: (prisma: PrismaClient) => Promise<void>;
@@ -12,6 +14,8 @@ export interface Script {
1214
export const scripts: Record<string, Script> = {
1315
"migrate-duplicate-connections": migrateDuplicateConnections,
1416
"inject-audit-data": injectAuditData,
17+
"inject-repo-data": injectRepoData,
18+
"test-repo-query-perf": testRepoQueryPerf,
1519
}
1620

1721
const parser = new ArgumentParser();
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import { Script } from "../scriptRunner";
2+
import { PrismaClient } from "../../dist";
3+
import { createLogger } from "@sourcebot/logger";
4+
5+
const logger = createLogger('inject-repo-data');
6+
7+
const NUM_REPOS = 100000;
8+
9+
export const injectRepoData: Script = {
10+
run: async (prisma: PrismaClient) => {
11+
const orgId = 1;
12+
13+
// Check if org exists
14+
const org = await prisma.org.findUnique({
15+
where: { id: orgId }
16+
});
17+
18+
if (!org) {
19+
await prisma.org.create({
20+
data: {
21+
id: orgId,
22+
name: 'Test Org',
23+
domain: 'test-org.com'
24+
}
25+
});
26+
}
27+
28+
const connection = await prisma.connection.create({
29+
data: {
30+
orgId,
31+
name: 'test-connection',
32+
connectionType: 'github',
33+
config: {}
34+
}
35+
});
36+
37+
38+
logger.info(`Creating ${NUM_REPOS} repos...`);
39+
40+
for (let i = 0; i < NUM_REPOS; i++) {
41+
await prisma.repo.create({
42+
data: {
43+
name: `test-repo-${i}`,
44+
isFork: false,
45+
isArchived: false,
46+
metadata: {},
47+
cloneUrl: `https://github.com/test-org/test-repo-${i}`,
48+
webUrl: `https://github.com/test-org/test-repo-${i}`,
49+
orgId,
50+
external_id: `test-repo-${i}`,
51+
external_codeHostType: 'github',
52+
external_codeHostUrl: 'https://github.com',
53+
connections: {
54+
create: {
55+
connectionId: connection.id,
56+
}
57+
}
58+
}
59+
});
60+
}
61+
62+
logger.info(`Created ${NUM_REPOS} repos.`);
63+
}
64+
};
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { Script } from "../scriptRunner";
2+
import { PrismaClient } from "../../dist";
3+
import { createLogger } from "@sourcebot/logger";
4+
5+
const logger = createLogger('test-repo-query-perf');
6+
7+
export const testRepoQueryPerf: Script = {
8+
run: async (prisma: PrismaClient) => {
9+
10+
11+
const start = Date.now();
12+
const allRepos = await prisma.repo.findMany({
13+
where: {
14+
orgId: 1,
15+
},
16+
include: {
17+
connections: {
18+
include: {
19+
connection: true,
20+
}
21+
}
22+
}
23+
});
24+
25+
const durationMs = Date.now() - start;
26+
logger.info(`Found ${allRepos.length} repos in ${durationMs}ms`);
27+
}
28+
};

0 commit comments

Comments
 (0)