Skip to content

Commit a52e97a

Browse files
fix(web): Improve /repos page performance (#677)
* fix * wip * changelog
1 parent 92d8abb commit a52e97a

File tree

8 files changed

+574
-130
lines changed

8 files changed

+574
-130
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1010
### Fixed
1111
- Fixed issue where parenthesis in query params were not being encoded, resulting in a poor experience when embedding links in Markdown. [#674](https://github.com/sourcebot-dev/sourcebot/pull/674)
1212
- Gitlab clone respects host protocol setting in environment variable. [#676](https://github.com/sourcebot-dev/sourcebot/pull/676)
13+
- Fixed performance issues with `/repos` page. [#677](https://github.com/sourcebot-dev/sourcebot/pull/677)
1314

1415
## [4.10.3] - 2025-12-12
1516

packages/backend/src/repoIndexManager.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,11 @@ export class RepoIndexManager {
258258
},
259259
data: {
260260
status: RepoIndexingJobStatus.IN_PROGRESS,
261+
repo: {
262+
update: {
263+
latestIndexingJobStatus: RepoIndexingJobStatus.IN_PROGRESS,
264+
}
265+
}
261266
},
262267
select: {
263268
type: true,
@@ -462,6 +467,11 @@ export class RepoIndexManager {
462467
data: {
463468
status: RepoIndexingJobStatus.COMPLETED,
464469
completedAt: new Date(),
470+
repo: {
471+
update: {
472+
latestIndexingJobStatus: RepoIndexingJobStatus.COMPLETED,
473+
}
474+
}
465475
},
466476
include: {
467477
repo: true,
@@ -522,6 +532,11 @@ export class RepoIndexManager {
522532
status: RepoIndexingJobStatus.FAILED,
523533
completedAt: new Date(),
524534
errorMessage: job.failedReason,
535+
repo: {
536+
update: {
537+
latestIndexingJobStatus: RepoIndexingJobStatus.FAILED,
538+
}
539+
}
525540
},
526541
select: { repo: true }
527542
});
@@ -550,6 +565,11 @@ export class RepoIndexManager {
550565
status: RepoIndexingJobStatus.FAILED,
551566
completedAt: new Date(),
552567
errorMessage: 'Job stalled',
568+
repo: {
569+
update: {
570+
latestIndexingJobStatus: RepoIndexingJobStatus.FAILED,
571+
}
572+
}
553573
},
554574
select: { repo: true, type: true }
555575
});
@@ -572,6 +592,11 @@ export class RepoIndexManager {
572592
status: RepoIndexingJobStatus.FAILED,
573593
completedAt: new Date(),
574594
errorMessage: 'Job timed out',
595+
repo: {
596+
update: {
597+
latestIndexingJobStatus: RepoIndexingJobStatus.FAILED,
598+
}
599+
}
575600
},
576601
select: { repo: true }
577602
});
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
-- AlterTable
2+
ALTER TABLE "Repo" ADD COLUMN "latestIndexingJobStatus" "RepoIndexingJobStatus";

packages/db/prisma/schema.prisma

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ model Repo {
6666
jobs RepoIndexingJob[]
6767
indexedAt DateTime? /// When the repo was last indexed successfully.
6868
indexedCommitHash String? /// The commit hash of the last indexed commit (on HEAD).
69+
latestIndexingJobStatus RepoIndexingJobStatus? /// The status of the latest indexing job.
6970
7071
external_id String /// The id of the repo in the external service
7172
external_codeHostType CodeHostType /// The type of the external service (e.g., github, gitlab, etc.)

packages/db/tools/scripts/inject-repo-data.ts

Lines changed: 52 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import { Script } from "../scriptRunner";
22
import { PrismaClient } from "../../dist";
33

4-
const NUM_REPOS = 100000;
4+
const NUM_REPOS = 1000;
5+
const NUM_INDEXING_JOBS_PER_REPO = 10000;
6+
const NUM_PERMISSION_JOBS_PER_REPO = 10000;
57

68
export const injectRepoData: Script = {
79
run: async (prisma: PrismaClient) => {
@@ -32,30 +34,60 @@ export const injectRepoData: Script = {
3234
});
3335

3436

35-
console.log(`Creating ${NUM_REPOS} repos...`);
37+
console.log(`Creating ${NUM_REPOS} repos...`);
3638

37-
for (let i = 0; i < NUM_REPOS; i++) {
38-
await prisma.repo.create({
39-
data: {
40-
name: `test-repo-${i}`,
41-
isFork: false,
42-
isArchived: false,
43-
metadata: {},
44-
cloneUrl: `https://github.com/test-org/test-repo-${i}`,
45-
webUrl: `https://github.com/test-org/test-repo-${i}`,
46-
orgId,
47-
external_id: `test-repo-${i}`,
48-
external_codeHostType: 'github',
49-
external_codeHostUrl: 'https://github.com',
50-
connections: {
51-
create: {
52-
connectionId: connection.id,
53-
}
39+
const statuses = ['PENDING', 'IN_PROGRESS', 'COMPLETED', 'FAILED'] as const;
40+
const indexingJobTypes = ['INDEX', 'CLEANUP'] as const;
41+
42+
for (let i = 0; i < NUM_REPOS; i++) {
43+
const repo = await prisma.repo.create({
44+
data: {
45+
name: `test-repo-${i}`,
46+
isFork: false,
47+
isArchived: false,
48+
metadata: {},
49+
cloneUrl: `https://github.com/test-org/test-repo-${i}`,
50+
webUrl: `https://github.com/test-org/test-repo-${i}`,
51+
orgId,
52+
external_id: `test-repo-${i}`,
53+
external_codeHostType: 'github',
54+
external_codeHostUrl: 'https://github.com',
55+
connections: {
56+
create: {
57+
connectionId: connection.id,
5458
}
5559
}
60+
}
61+
});
62+
63+
for (let j = 0; j < NUM_PERMISSION_JOBS_PER_REPO; j++) {
64+
const status = statuses[Math.floor(Math.random() * statuses.length)];
65+
await prisma.repoPermissionSyncJob.create({
66+
data: {
67+
repoId: repo.id,
68+
status,
69+
completedAt: status === 'COMPLETED' || status === 'FAILED' ? new Date() : null,
70+
errorMessage: status === 'FAILED' ? 'Mock error message' : null
71+
}
5672
});
5773
}
5874

59-
console.log(`Created ${NUM_REPOS} repos.`);
75+
for (let j = 0; j < NUM_INDEXING_JOBS_PER_REPO; j++) {
76+
const status = statuses[Math.floor(Math.random() * statuses.length)];
77+
const type = indexingJobTypes[Math.floor(Math.random() * indexingJobTypes.length)];
78+
await prisma.repoIndexingJob.create({
79+
data: {
80+
repoId: repo.id,
81+
type,
82+
status,
83+
completedAt: status === 'COMPLETED' || status === 'FAILED' ? new Date() : null,
84+
errorMessage: status === 'FAILED' ? 'Mock indexing error' : null,
85+
metadata: {}
86+
}
87+
});
88+
}
89+
}
90+
91+
console.log(`Created ${NUM_REPOS} repos with associated jobs.`);
6092
}
6193
};

0 commit comments

Comments
 (0)