@@ -37,9 +37,13 @@ export class ProcessPlatformAdapter implements PlatformAdapter<SupabaseResources
3737 private readonly queries : Queries ;
3838 private worker : Worker | null = null ;
3939 private workerId : string | null = null ;
40+ private startupPromise : Promise < void > | null = null ;
4041 private stopPromise : Promise < void > | null = null ;
4142 private gracefulExitPromise : Promise < void > | null = null ;
43+ private cleanupPromise : Promise < void > | null = null ;
44+ private signalHandlersRegistered = false ;
4245 private signalCount = 0 ;
46+ private readonly signalHandler = ( ) => this . handleSignal ( ) ;
4347
4448 constructor (
4549 options ?: ProcessAdapterOptions ,
@@ -48,41 +52,34 @@ export class ProcessPlatformAdapter implements PlatformAdapter<SupabaseResources
4852 this . deps = deps ;
4953 this . assertProcessEnv ( deps . env ) ;
5054 this . validatedEnv = deps . env ;
51- this . _connectionString = resolveConnectionString ( this . validatedEnv , {
55+ const connectionOptions = {
56+ ...options ,
5257 hasSql : ! ! options ?. sql ,
53- connectionString : options ?. connectionString ,
54- } ) ;
58+ allowDatabaseUrl : true ,
59+ } ;
60+ this . _connectionString = resolveConnectionString (
61+ this . validatedEnv ,
62+ connectionOptions
63+ ) ;
5564 this . ownsSql = ! options ?. sql ;
5665 this . loggingFactory = createLoggingFactory ( this . validatedEnv ) ;
5766 this . logger = this . loggingFactory . createLogger ( 'ProcessPlatformAdapter' ) ;
5867 this . _platformResources = {
59- sql : resolveSqlConnection ( this . validatedEnv , options ) ,
68+ sql : resolveSqlConnection ( this . validatedEnv , connectionOptions ) ,
6069 supabase : createServiceSupabaseClient ( this . validatedEnv ) ,
6170 } ;
6271 this . queries = new Queries ( this . _platformResources . sql ) ;
6372 }
6473
65- async startWorker ( createWorkerFn : CreateWorkerFn ) : Promise < void > {
66- const workerName = this . validatedEnv . WORKER_NAME || 'pgflow-worker' ;
67- const workerId = this . deps . randomUUID ( ) ;
68-
69- this . workerId = workerId ;
70- this . loggingFactory . setWorkerId ( workerId ) ;
71- this . loggingFactory . setWorkerName ( workerName ) ;
72-
73- this . worker = createWorkerFn ( this . loggingFactory . createLogger ) ;
74-
75- this . worker . onDeprecated ( ( ) => {
76- this . handleDeprecation ( ) . catch ( ( ) => undefined ) ;
77- } ) ;
78-
79- await this . worker . startOnlyOnce ( {
80- edgeFunctionName : workerName ,
81- workerId,
82- startMode : 'process' ,
83- } ) ;
84-
74+ startWorker ( createWorkerFn : CreateWorkerFn ) : Promise < void > {
8575 this . registerSignalHandlers ( ) ;
76+ this . startupPromise ??= this . performStartWorker ( createWorkerFn ) . catch (
77+ async ( error ) => {
78+ await this . cleanup ( ) ;
79+ throw error ;
80+ }
81+ ) ;
82+ return this . startupPromise ;
8683 }
8784
8885 stopWorker ( ) : Promise < void > {
@@ -126,27 +123,68 @@ export class ProcessPlatformAdapter implements PlatformAdapter<SupabaseResources
126123 return this . _platformResources . supabase ;
127124 }
128125
126+ private async performStartWorker ( createWorkerFn : CreateWorkerFn ) : Promise < void > {
127+ const workerName = this . validatedEnv . WORKER_NAME || 'pgflow-worker' ;
128+ const workerId = this . deps . randomUUID ( ) ;
129+
130+ this . workerId = workerId ;
131+ this . loggingFactory . setWorkerId ( workerId ) ;
132+ this . loggingFactory . setWorkerName ( workerName ) ;
133+
134+ this . worker = createWorkerFn ( this . loggingFactory . createLogger ) ;
135+ this . worker . onDeprecated ( ( ) => {
136+ this . handleDeprecation ( ) . catch ( ( ) => undefined ) ;
137+ } ) ;
138+
139+ await this . worker . startOnlyOnce ( {
140+ edgeFunctionName : workerName ,
141+ workerId,
142+ startMode : 'process' ,
143+ } ) ;
144+ }
145+
129146 private registerSignalHandlers ( ) : void {
147+ if ( this . signalHandlersRegistered ) return ;
148+
149+ this . signalHandlersRegistered = true ;
130150 for ( const signal of [ 'SIGTERM' , 'SIGINT' , 'SIGQUIT' ] satisfies ProcessSignal [ ] ) {
131- this . deps . onSignal ( signal , ( ) => this . handleSignal ( ) ) ;
151+ this . deps . onSignal ( signal , this . signalHandler ) ;
152+ }
153+ }
154+
155+ private removeSignalHandlers ( ) : void {
156+ if ( ! this . signalHandlersRegistered ) return ;
157+
158+ this . signalHandlersRegistered = false ;
159+ for ( const signal of [ 'SIGTERM' , 'SIGINT' , 'SIGQUIT' ] satisfies ProcessSignal [ ] ) {
160+ this . deps . offSignal ?.( signal , this . signalHandler ) ;
132161 }
133162 }
134163
135164 private async performStopWorker ( ) : Promise < void > {
136165 this . requestShutdown ( ) ;
137166
138167 try {
168+ await this . startupPromise ;
139169 if ( this . worker ) {
140170 await this . worker . stop ( ) ;
141171 }
142172 if ( this . workerId ) {
143173 await this . queries . markWorkerStopped ( this . workerId ) ;
144174 }
145175 } finally {
176+ await this . cleanup ( ) ;
177+ }
178+ }
179+
180+ private cleanup ( ) : Promise < void > {
181+ this . cleanupPromise ??= ( async ( ) => {
182+ this . removeSignalHandlers ( ) ;
146183 if ( this . ownsSql ) {
147184 await this . _platformResources . sql . end ( ) ;
148185 }
149- }
186+ } ) ( ) ;
187+ return this . cleanupPromise ;
150188 }
151189
152190 private gracefulExit ( ) : Promise < void > {
0 commit comments