Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fixed spurious infinite loads with explore panel, file tree, and file search command. [#617](https://github.com/sourcebot-dev/sourcebot/pull/617)
- Wipe search context on init if entitlement no longer exists [#618](https://github.com/sourcebot-dev/sourcebot/pull/618)
- Fixed Bitbucket repository exclusions not supporting glob patterns. [#620](https://github.com/sourcebot-dev/sourcebot/pull/620)
- Fixed issue where the repo driven permission syncer was attempting to sync public repositories. [#624](https://github.com/sourcebot-dev/sourcebot/pull/624)
- Fixed issue where worker would not shutdown while a permission sync job (repo or user) was in progress. [#624](https://github.com/sourcebot-dev/sourcebot/pull/624)

## [4.9.2] - 2025-11-13

Expand Down
2 changes: 1 addition & 1 deletion packages/backend/src/ee/accountPermissionSyncer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ export class AccountPermissionSyncer {
if (this.interval) {
clearInterval(this.interval);
}
await this.worker.close();
await this.worker.close(/* force = */ true);
await this.queue.close();
}

Expand Down
12 changes: 10 additions & 2 deletions packages/backend/src/ee/repoPermissionSyncer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,19 +55,27 @@ export class RepoPermissionSyncer {
const repos = await this.db.repo.findMany({
// Repos need their permissions to be synced against the code host when...
where: {
// They belong to a code host that supports permissions syncing
AND: [
// They are not public. Public repositories are always visible to all users, therefore we don't
// need to explicitly perform permission syncing for them.
// @see: packages/web/src/prisma.ts
{
isPublic: false
},
// They belong to a code host that supports permissions syncing
{
external_codeHostType: {
in: PERMISSION_SYNC_SUPPORTED_CODE_HOST_TYPES,
}
},
// They have not been synced within the threshold date.
{
OR: [
{ permissionSyncedAt: null },
{ permissionSyncedAt: { lt: thresholdDate } },
],
},
// There aren't any active or recently failed jobs.
{
NOT: {
permissionSyncJobs: {
Expand Down Expand Up @@ -106,7 +114,7 @@ export class RepoPermissionSyncer {
if (this.interval) {
clearInterval(this.interval);
}
await this.worker.close();
await this.worker.close(/* force = */ true);
await this.queue.close();
}

Expand Down
11 changes: 6 additions & 5 deletions packages/backend/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,35 +111,36 @@ const listenToShutdownSignals = () => {
await redis.quit();
await api.dispose();
await shutdownPosthog();


logger.info('All workers shut down gracefully');
signals.forEach(sig => process.removeListener(sig, cleanup));
return 0;
} catch (error) {
Sentry.captureException(error);
logger.error('Error shutting down worker:', error);
return 1;
}
}

signals.forEach(signal => {
process.on(signal, (err) => {
cleanup(err).finally(() => {
process.kill(process.pid, signal);
cleanup(err).then(code => {
process.exit(code);
});
});
});

// Register handlers for uncaught exceptions and unhandled rejections
process.on('uncaughtException', (err) => {
logger.error(`Uncaught exception: ${err.message}`);
cleanup('uncaughtException').finally(() => {
cleanup('uncaughtException').then(() => {
process.exit(1);
});
});

process.on('unhandledRejection', (reason, promise) => {
logger.error(`Unhandled rejection at: ${promise}, reason: ${reason}`);
cleanup('unhandledRejection').finally(() => {
cleanup('unhandledRejection').then(() => {
process.exit(1);
});
});
Expand Down
Loading