@@ -31,6 +31,19 @@ const debuglog = util.debuglog('cdbg.firebase');
3131
3232const FIREBASE_APP_NAME = 'cdbg' ;
3333
34+ /**
35+ * Waits ms milliseconds for the promise to resolve, or rejects with a timeout.
36+ * @param ms
37+ * @param promise
38+ * @returns Promise wrapped in a timeout.
39+ */
40+ const withTimeout = ( ms : number , promise : Promise < any > ) => {
41+ const timeout = new Promise ( ( _ , reject ) =>
42+ setTimeout ( ( ) => reject ( `Timed out after ${ ms } ms.` ) , ms )
43+ ) ;
44+ return Promise . race ( [ promise , timeout ] ) ;
45+ } ;
46+
3447export class FirebaseController implements Controller {
3548 db : firebase . database . Database ;
3649 debuggeeId ?: string ;
@@ -75,54 +88,62 @@ export class FirebaseController implements Controller {
7588 }
7689
7790 // Build the database URL.
78- let databaseUrl : string ;
91+ const databaseUrls = [ ] ;
7992 if ( options . databaseUrl ) {
80- databaseUrl = options . databaseUrl ;
93+ databaseUrls . push ( options . databaseUrl ) ;
8194 } else {
82- // TODO: Add fallback to -default
83- databaseUrl = `https://${ projectId } -cdbg .firebaseio.com` ;
95+ databaseUrls . push ( `https:// ${ projectId } -cdbg.firebaseio.com` ) ;
96+ databaseUrls . push ( `https://${ projectId } -default-rtdb .firebaseio.com` ) ;
8497 }
8598
86- let app : firebase . app . App ;
87- if ( credential ) {
88- app = firebase . initializeApp (
89- {
90- credential : credential ,
91- databaseURL : databaseUrl ,
92- } ,
93- FIREBASE_APP_NAME
94- ) ;
95- } else {
96- // Use the default credentials.
97- app = firebase . initializeApp (
98- {
99- databaseURL : databaseUrl ,
100- } ,
101- FIREBASE_APP_NAME
102- ) ;
103- }
99+ for ( const databaseUrl of databaseUrls ) {
100+ let app : firebase . app . App ;
101+ if ( credential ) {
102+ app = firebase . initializeApp (
103+ {
104+ credential : credential ,
105+ databaseURL : databaseUrl ,
106+ } ,
107+ FIREBASE_APP_NAME
108+ ) ;
109+ } else {
110+ // Use the default credentials.
111+ app = firebase . initializeApp (
112+ {
113+ databaseURL : databaseUrl ,
114+ } ,
115+ FIREBASE_APP_NAME
116+ ) ;
117+ }
104118
105- const db = firebase . database ( app ) ;
119+ const db = firebase . database ( app ) ;
106120
107- // Test the connection by reading the schema version.
108- try {
109- const version_snapshot = await db . ref ( 'cdbg/schema_version' ) . get ( ) ;
110- if ( version_snapshot ) {
111- const version = version_snapshot . val ( ) ;
112- debuglog (
113- `Firebase app initialized. Connected to ${ databaseUrl } ` +
114- ` with schema version ${ version } `
121+ // Test the connection by reading the schema version.
122+ try {
123+ const version_snapshot = await withTimeout (
124+ 10000 ,
125+ db . ref ( 'cdbg/schema_version' ) . get ( )
115126 ) ;
116- } else {
127+ if ( version_snapshot ) {
128+ const version = version_snapshot . val ( ) ;
129+ debuglog (
130+ `Firebase app initialized. Connected to ${ databaseUrl } ` +
131+ ` with schema version ${ version } `
132+ ) ;
133+
134+ return db ;
135+ } else {
136+ throw new Error ( 'failed to fetch schema version from database' ) ;
137+ }
138+ } catch ( e ) {
139+ debuglog ( `failed to connect to database ${ databaseUrl } : ` + e ) ;
117140 app . delete ( ) ;
118- throw new Error ( 'failed to fetch schema version from database' ) ;
119141 }
120- } catch ( e ) {
121- app . delete ( ) ;
122- throw e ;
123142 }
124143
125- return db ;
144+ throw new Error (
145+ `Failed to initialize FirebaseApp, attempted URLs: ${ databaseUrls } `
146+ ) ;
126147 }
127148
128149 /**
0 commit comments