1515import express from 'express' ;
1616import { resolve } from 'node:path' ;
1717import fs from 'node:fs' ;
18- import { Connector , IpAddressTypes , AuthTypes } from '@google-cloud/cloud-sql-connector' ;
18+ import {
19+ Connector ,
20+ IpAddressTypes ,
21+ AuthTypes ,
22+ } from '@google-cloud/cloud-sql-connector' ;
1923import { PrismaClient } from '@prisma/client' ;
2024
2125const app = express ( ) ;
@@ -58,28 +62,31 @@ async function getIamConnection() {
5862
5963 // Creates a randomly named unix socket path for the local proxy.
6064 const dir = resolve ( '/tmp' , `pg-iam-${ Date . now ( ) } ` ) ;
61- fs . mkdirSync ( dir , { recursive : true } ) ;
65+ fs . mkdirSync ( dir , { recursive : true } ) ;
6266 const path = resolve ( dir , '.s.PGSQL.5432' ) ;
6367
6468 // The startLocalProxy method starts a local proxy that listens on the
6569 // specified unix socket path. This allows the application to connect to
6670 // the database using a standard database driver.
67- await connector . startLocalProxy ( {
71+ const cleanup = await connector . startLocalProxy ( {
6872 instanceConnectionName,
6973 ipType : ipType ,
7074 authType : AuthTypes . IAM ,
7175 listenOptions : { path} ,
7276 } ) ;
7377
7478 // URL encode the user for IAM service accounts
75- const datasourceUrl = `postgresql://${ encodeURIComponent ( dbUser ) } @localhost/${ dbName } ?host=${ dir } ` ;
79+ const datasourceUrl = `postgresql://${ encodeURIComponent (
80+ dbUser
81+ ) } @localhost/${ dbName } ?host=${ dir } `;
7682 const prisma = new PrismaClient ( { datasourceUrl} ) ;
7783
7884 // Returns the prisma client and a cleanup function to close the connection.
7985 return {
8086 prisma,
8187 async close ( ) {
8288 await prisma . $disconnect ( ) ;
89+ cleanup ( ) ;
8390 } ,
8491 } ;
8592}
@@ -100,13 +107,13 @@ async function getPasswordConnection() {
100107
101108 // Creates a randomly named unix socket path for the local proxy.
102109 const dir = resolve ( '/tmp' , `pg-pw-${ Date . now ( ) } ` ) ;
103- fs . mkdirSync ( dir , { recursive : true } ) ;
110+ fs . mkdirSync ( dir , { recursive : true } ) ;
104111 const path = resolve ( dir , '.s.PGSQL.5432' ) ;
105112
106113 // The startLocalProxy method starts a local proxy that listens on the
107114 // specified unix socket path. This allows the application to connect to
108115 // the database using a standard database driver.
109- await connector . startLocalProxy ( {
116+ const cleanup = await connector . startLocalProxy ( {
110117 instanceConnectionName,
111118 ipType : ipType ,
112119 listenOptions : { path} ,
@@ -122,14 +129,15 @@ async function getPasswordConnection() {
122129 prisma,
123130 async close ( ) {
124131 await prisma . $disconnect ( ) ;
132+ cleanup ( ) ;
125133 } ,
126134 } ;
127135}
128136
129137// Helper to get or create the password pool
130138async function getConnectionSettings ( ) {
131139 if ( ! passwordClient ) {
132- const { prisma, close } = await getPasswordConnection ( ) ;
140+ const { prisma, close} = await getPasswordConnection ( ) ;
133141 passwordClient = prisma ;
134142 passwordCleanup = close ;
135143 }
@@ -139,7 +147,7 @@ async function getConnectionSettings() {
139147// Helper to get or create the IAM pool
140148async function getIamConnectionSettings ( ) {
141149 if ( ! iamClient ) {
142- const { prisma, close } = await getIamConnection ( ) ;
150+ const { prisma, close} = await getIamConnection ( ) ;
143151 iamClient = prisma ;
144152 iamCleanup = close ;
145153 }
@@ -151,12 +159,20 @@ app.get('/', async (req, res) => {
151159 const prisma = await getConnectionSettings ( ) ;
152160 const result = await prisma . $queryRaw `SELECT 1` ;
153161 const serialized = JSON . stringify ( result , ( key , value ) =>
154- typeof value === 'bigint' ? value . toString ( ) : value
162+ typeof value === 'bigint' ? value . toString ( ) : value
155163 ) ;
156- res . send ( `Database connection successful (password authentication), result: ${ serialized } ` ) ;
157- } catch ( err : any ) {
164+ res . send (
165+ 'Database connection successful (password authentication), result: ' +
166+ `${ serialized } `
167+ ) ;
168+ } catch ( err : unknown ) {
158169 console . error ( err ) ;
159- res . status ( 500 ) . send ( `Error connecting to the database (password authentication): ${ err . message } ` ) ;
170+ res
171+ . status ( 500 )
172+ . send (
173+ 'Error connecting to the database (password authentication): ' +
174+ `${ ( err as Error ) . message } `
175+ ) ;
160176 }
161177} ) ;
162178
@@ -165,12 +181,20 @@ app.get('/iam', async (req, res) => {
165181 const prisma = await getIamConnectionSettings ( ) ;
166182 const result = await prisma . $queryRaw `SELECT 1` ;
167183 const serialized = JSON . stringify ( result , ( key , value ) =>
168- typeof value === 'bigint' ? value . toString ( ) : value
184+ typeof value === 'bigint' ? value . toString ( ) : value
185+ ) ;
186+ res . send (
187+ 'Database connection successful (IAM authentication), result: ' +
188+ `${ serialized } `
169189 ) ;
170- res . send ( `Database connection successful (IAM authentication), result: ${ serialized } ` ) ;
171- } catch ( err : any ) {
190+ } catch ( err : unknown ) {
172191 console . error ( err ) ;
173- res . status ( 500 ) . send ( `Error connecting to the database (IAM authentication): ${ err . message } ` ) ;
192+ res
193+ . status ( 500 )
194+ . send (
195+ 'Error connecting to the database (IAM authentication): ' +
196+ `${ ( err as Error ) . message } `
197+ ) ;
174198 }
175199} ) ;
176200
@@ -179,3 +203,15 @@ const port = process.env.PORT ? parseInt(process.env.PORT) : 8080;
179203app . listen ( port , ( ) => {
180204 console . log ( `Listening on port ${ port } ` ) ;
181205} ) ;
206+
207+ process . on ( 'SIGTERM' , async ( ) => {
208+ if ( passwordCleanup ) {
209+ await passwordCleanup ( ) ;
210+ }
211+ if ( iamCleanup ) {
212+ await iamCleanup ( ) ;
213+ }
214+ if ( connector ) {
215+ connector . close ( ) ;
216+ }
217+ } ) ;
0 commit comments