11import "./instrument.js" ;
22
3- import * as Sentry from "@sentry/node" ;
3+ import { PrismaClient } from "@sourcebot/db" ;
4+ import { createLogger } from "@sourcebot/logger" ;
5+ import { loadConfig } from '@sourcebot/shared' ;
46import { existsSync } from 'fs' ;
57import { mkdir } from 'fs/promises' ;
8+ import { Redis } from 'ioredis' ;
69import path from 'path' ;
7- import { AppContext } from "./types.js" ;
8- import { main } from "./main.js"
9- import { PrismaClient } from "@sourcebot/db" ;
10+ import { ConnectionManager } from './connectionManager.js' ;
11+ import { DEFAULT_SETTINGS } from './constants.js' ;
1012import { env } from "./env.js" ;
11- import { createLogger } from "@sourcebot/logger" ;
12-
13- const logger = createLogger ( 'backend-entrypoint' ) ;
13+ import { RepoPermissionSyncer } from './permissionSyncer.js' ;
14+ import { PromClient } from './promClient.js' ;
15+ import { RepoManager } from './repoManager.js' ;
16+ import { AppContext } from "./types.js" ;
1417
1518
16- // Register handler for normal exit
17- process . on ( 'exit' , ( code ) => {
18- logger . info ( `Process is exiting with code: ${ code } ` ) ;
19- } ) ;
19+ const logger = createLogger ( 'backend-entrypoint' ) ;
2020
21- // Register handlers for abnormal terminations
22- process . on ( 'SIGINT' , ( ) => {
23- logger . info ( 'Process interrupted (SIGINT)' ) ;
24- process . exit ( 0 ) ;
25- } ) ;
21+ const getSettings = async ( configPath ?: string ) => {
22+ if ( ! configPath ) {
23+ return DEFAULT_SETTINGS ;
24+ }
2625
27- process . on ( 'SIGTERM' , ( ) => {
28- logger . info ( 'Process terminated (SIGTERM)' ) ;
29- process . exit ( 0 ) ;
30- } ) ;
26+ const config = await loadConfig ( configPath ) ;
3127
32- // Register handlers for uncaught exceptions and unhandled rejections
33- process . on ( 'uncaughtException' , ( err ) => {
34- logger . error ( `Uncaught exception: ${ err . message } ` ) ;
35- process . exit ( 1 ) ;
36- } ) ;
28+ return {
29+ ... DEFAULT_SETTINGS ,
30+ ... config . settings ,
31+ }
32+ }
3733
38- process . on ( 'unhandledRejection' , ( reason , promise ) => {
39- logger . error ( `Unhandled rejection at: ${ promise } , reason: ${ reason } ` ) ;
40- process . exit ( 1 ) ;
41- } ) ;
4234
4335const cacheDir = env . DATA_CACHE_DIR ;
4436const reposPath = path . join ( cacheDir , 'repos' ) ;
@@ -59,18 +51,60 @@ const context: AppContext = {
5951
6052const prisma = new PrismaClient ( ) ;
6153
62- main ( prisma , context )
63- . then ( async ( ) => {
64- await prisma . $disconnect ( ) ;
65- } )
66- . catch ( async ( e ) => {
67- logger . error ( e ) ;
68- Sentry . captureException ( e ) ;
69-
70- await prisma . $disconnect ( ) ;
71- process . exit ( 1 ) ;
72- } )
73- . finally ( ( ) => {
74- logger . info ( "Shutting down..." ) ;
75- } ) ;
54+ const redis = new Redis ( env . REDIS_URL , {
55+ maxRetriesPerRequest : null
56+ } ) ;
57+ redis . ping ( ) . then ( ( ) => {
58+ logger . info ( 'Connected to redis' ) ;
59+ } ) . catch ( ( err : unknown ) => {
60+ logger . error ( 'Failed to connect to redis' ) ;
61+ logger . error ( err ) ;
62+ process . exit ( 1 ) ;
63+ } ) ;
64+
65+ const promClient = new PromClient ( ) ;
66+
67+ const settings = await getSettings ( env . CONFIG_PATH ) ;
68+
69+ const connectionManager = new ConnectionManager ( prisma , settings , redis ) ;
70+ const repoManager = new RepoManager ( prisma , settings , redis , promClient , context ) ;
71+ const permissionSyncer = new RepoPermissionSyncer ( prisma , redis ) ;
72+
73+ await repoManager . validateIndexedReposHaveShards ( ) ;
74+
75+ const connectionManagerInterval = connectionManager . startScheduler ( ) ;
76+ const repoManagerInterval = repoManager . startScheduler ( ) ;
77+ const permissionSyncerInterval = env . EXPERIMENT_PERMISSION_SYNC_ENABLED ? permissionSyncer . startScheduler ( ) : null ;
78+
79+
80+ const cleanup = async ( signal : string ) => {
81+ logger . info ( `Recieved ${ signal } , cleaning up...` ) ;
82+
83+ if ( permissionSyncerInterval ) {
84+ clearInterval ( permissionSyncerInterval ) ;
85+ }
86+
87+ clearInterval ( connectionManagerInterval ) ;
88+ clearInterval ( repoManagerInterval ) ;
89+
90+ connectionManager . dispose ( ) ;
91+ repoManager . dispose ( ) ;
92+ permissionSyncer . dispose ( ) ;
7693
94+ await prisma . $disconnect ( ) ;
95+ await redis . quit ( ) ;
96+ }
97+
98+ process . on ( 'SIGINT' , ( ) => cleanup ( 'SIGINT' ) . finally ( ( ) => process . exit ( 0 ) ) ) ;
99+ process . on ( 'SIGTERM' , ( ) => cleanup ( 'SIGTERM' ) . finally ( ( ) => process . exit ( 0 ) ) ) ;
100+
101+ // Register handlers for uncaught exceptions and unhandled rejections
102+ process . on ( 'uncaughtException' , ( err ) => {
103+ logger . error ( `Uncaught exception: ${ err . message } ` ) ;
104+ cleanup ( 'uncaughtException' ) . finally ( ( ) => process . exit ( 1 ) ) ;
105+ } ) ;
106+
107+ process . on ( 'unhandledRejection' , ( reason , promise ) => {
108+ logger . error ( `Unhandled rejection at: ${ promise } , reason: ${ reason } ` ) ;
109+ cleanup ( 'unhandledRejection' ) . finally ( ( ) => process . exit ( 1 ) ) ;
110+ } ) ;
0 commit comments