Skip to content
This repository was archived by the owner on Apr 3, 2024. It is now read-only.

Commit 8cd89c8

Browse files
authored
fix: add timeout to firebase db connection attempt (#1132)
Firebase database reads/writes can hang indefinitely if there is an issue with the credentials or with the database url. Fixing https://togithub.com/firebase/firebase-admin-node/issues/2004 will address this issue, but until then this PR adds a timeout to ensure that errors are emitted.
1 parent afe9f53 commit 8cd89c8

File tree

1 file changed

+58
-37
lines changed

1 file changed

+58
-37
lines changed

src/agent/firebase-controller.ts

Lines changed: 58 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,19 @@ const debuglog = util.debuglog('cdbg.firebase');
3131

3232
const 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+
3447
export 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

Comments
 (0)