1
1
import "./instrument.js" ;
2
2
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' ;
4
6
import { existsSync } from 'fs' ;
5
7
import { mkdir } from 'fs/promises' ;
8
+ import { Redis } from 'ioredis' ;
6
9
import 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' ;
10
12
import { 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" ;
14
17
15
18
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' ) ;
20
20
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
+ }
26
25
27
- process . on ( 'SIGTERM' , ( ) => {
28
- logger . info ( 'Process terminated (SIGTERM)' ) ;
29
- process . exit ( 0 ) ;
30
- } ) ;
26
+ const config = await loadConfig ( configPath ) ;
31
27
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
+ }
37
33
38
- process . on ( 'unhandledRejection' , ( reason , promise ) => {
39
- logger . error ( `Unhandled rejection at: ${ promise } , reason: ${ reason } ` ) ;
40
- process . exit ( 1 ) ;
41
- } ) ;
42
34
43
35
const cacheDir = env . DATA_CACHE_DIR ;
44
36
const reposPath = path . join ( cacheDir , 'repos' ) ;
@@ -59,18 +51,60 @@ const context: AppContext = {
59
51
60
52
const prisma = new PrismaClient ( ) ;
61
53
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 ( ) ;
76
93
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