Skip to content

Commit 9e5ec47

Browse files
committed
Prepare v1.4.0
1 parent 4f49678 commit 9e5ec47

File tree

6 files changed

+228
-52
lines changed

6 files changed

+228
-52
lines changed

CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,20 @@ This change log follows the format documented in [Keep a CHANGELOG].
77
[semantic versioning]: https://semver.org
88
[keep a changelog]: https://keepachangelog.com
99

10+
## 1.4.0 - 2022-06-03
11+
12+
### Changed
13+
14+
- Set default `memory` (`1GB`) and `timeoutSeconds` (`540`) Firebase Functions runtime options. It solves the problem with the huge users' backups that either run out of memory or timeout.
15+
16+
- Even further improved the memory usage by the users backup.
17+
18+
- Updated dependencies to the latest supported versions.
19+
20+
### Added
21+
22+
- Added delayed users backup feature. If the delay is requested, the agent will respond with a pending backup state. When the backup is completed, the agent will notify the controller. That prevents multiple backups caused by timeouts.
23+
1024
## 1.3.0 - 2022-06-01
1125

1226
### Fixed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@backupfire/firebase",
3-
"version": "1.3.0",
3+
"version": "1.4.0",
44
"description": "Backup Fire Firebase agent",
55
"keywords": [
66
"backup Firebase database",

src/_lib/operation/index.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@ export type FirestoreStatusResponse =
1616

1717
export type UsersStatusResponse =
1818
| {
19-
state: 'completed' | 'pending'
19+
state: 'pending'
20+
}
21+
| {
22+
state: 'completed'
2023
data: {
2124
usersCount: number | undefined
2225
size: string

src/index.ts

Lines changed: 56 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -8,39 +8,41 @@ import { format } from 'url'
88
import {
99
backupFirestoreMiddleware,
1010
checkFirestoreBackupStatusMiddleware,
11-
getCollectionsMiddleware
11+
getCollectionsMiddleware,
1212
} from './firestore'
1313
import {
14-
listFilesMiddleware,
14+
defaultControllerDomain,
15+
defaultMemory,
16+
defaultRegion,
17+
defaultTimeout,
18+
} from './options'
19+
import {
1520
createStorageMiddleware,
21+
listFilesMiddleware,
1622
storageListMiddleware,
17-
updateStorageMiddleware
23+
updateStorageMiddleware,
1824
} from './storage'
1925
import {
2026
AgentOptions,
2127
BackupFireEnvConfig,
2228
BackupFireHTTPSHandler,
2329
BackupFireOptions,
24-
RuntimeEnvironment
30+
RuntimeEnvironment,
2531
} from './types'
2632
import { backupUsersMiddleware } from './users'
2733
import version from './version'
2834
import {
2935
configureExceptionsScope,
3036
createCrashedApp,
3137
exceptionHandlerMiddleware,
32-
initExceptionsTracker
38+
initExceptionsTracker,
3339
} from './_lib/exceptions'
3440

35-
export const defaultControllerDomain = 'backupfire.dev'
36-
37-
export const defaultRegion = 'us-central1'
38-
3941
export enum BackupFireConfig {
4042
Token = 'BACKUPFIRE_TOKEN',
4143
Password = 'BACKUPFIRE_PASSWORD',
4244
Domain = 'BACKUPFIRE_DOMAIN',
43-
Allowlist = 'BACKUPFIRE_ALLOWLIST'
45+
Allowlist = 'BACKUPFIRE_ALLOWLIST',
4446
}
4547

4648
// Fallback for CommonJS
@@ -60,7 +62,7 @@ export default function backupFire(agentOptions?: AgentOptions) {
6062
return dummyHandler({
6163
region: agentOptions?.region,
6264
memory: agentOptions?.memory,
63-
timeout: agentOptions?.timeout
65+
timeout: agentOptions?.timeout,
6466
})
6567

6668
// Derive Backup Fire options from environment configuration
@@ -80,7 +82,7 @@ export default function backupFire(agentOptions?: AgentOptions) {
8082
controllerToken: envConfig.token,
8183
adminPassword: envConfig.password,
8284
bucketsAllowlist: envConfig.allowlist?.split(','),
83-
debug: envConfig.debug === 'true'
85+
debug: envConfig.debug === 'true',
8486
},
8587
agentOptions
8688
)
@@ -111,7 +113,7 @@ export default function backupFire(agentOptions?: AgentOptions) {
111113
}
112114

113115
// Set additional context
114-
configureExceptionsScope(scope => {
116+
configureExceptionsScope((scope) => {
115117
scope.setUser({ id: envConfig.token })
116118
scope.setTag('project_id', runtimeEnv.projectId)
117119
scope.setTag('node_version', process.version)
@@ -131,12 +133,12 @@ export default function backupFire(agentOptions?: AgentOptions) {
131133
return httpsHandler({
132134
handler: createApp(runtimeEnv, options),
133135
agentOptions,
134-
runtimeEnv
136+
runtimeEnv,
135137
})
136138
} catch (err) {
137139
return httpsHandler({
138140
handler: createCrashedApp(err),
139-
agentOptions
141+
agentOptions,
140142
})
141143
}
142144
}
@@ -173,7 +175,7 @@ export function createApp(
173175
'/firestore',
174176
backupFirestoreMiddleware({
175177
projectId: runtimeEnv.projectId,
176-
...globalOptions
178+
...globalOptions,
177179
})
178180
)
179181
// Check Firestore backup status
@@ -185,7 +187,13 @@ export function createApp(
185187
// Backup Firebase users
186188
app.post(
187189
'/users',
188-
backupUsersMiddleware({ projectId: runtimeEnv.projectId, ...globalOptions })
190+
backupUsersMiddleware({
191+
projectId: runtimeEnv.projectId,
192+
controllerToken: options.controllerToken,
193+
controllerDomain: options.controllerDomain,
194+
agentURL: agentURL(runtimeEnv),
195+
...globalOptions,
196+
})
189197
)
190198

191199
// List storage
@@ -197,7 +205,7 @@ export function createApp(
197205
'/storage/:storageId',
198206
updateStorageMiddleware({
199207
adminPassword: options.adminPassword,
200-
...globalOptions
208+
...globalOptions,
201209
})
202210
)
203211
// List files in the storage
@@ -217,21 +225,16 @@ interface HTTPSHandlerProps {
217225
function httpsHandler({
218226
handler,
219227
agentOptions,
220-
runtimeEnv
228+
runtimeEnv,
221229
}: HTTPSHandlerProps) {
222230
if (runtimeEnv?.extensionId) {
223231
return functions.handler.https.onRequest(handler)
224232
} else {
225-
const runtimeOptions: functions.RuntimeOptions = {
226-
secrets: Object.values(BackupFireConfig)
227-
}
228-
229-
if (agentOptions?.memory) runtimeOptions.memory = agentOptions.memory
230-
if (agentOptions?.timeout)
231-
runtimeOptions.timeoutSeconds = agentOptions.timeout
232-
233233
return functions
234-
.runWith(runtimeOptions)
234+
.runWith({
235+
...getRuntimeOptions(agentOptions),
236+
secrets: Object.values(BackupFireConfig),
237+
})
235238
.region(agentOptions?.region || defaultRegion)
236239
.https.onRequest(handler)
237240
}
@@ -253,8 +256,8 @@ function sendInitializationPing(
253256
token: options.controllerToken,
254257
projectId: runtimeEnv.projectId,
255258
runtime: runtimeEnv.region,
256-
agentURL: agentURL(runtimeEnv)
257-
}
259+
agentURL: agentURL(runtimeEnv),
260+
},
258261
})
259262
return fetch(pingURL)
260263
}
@@ -290,7 +293,7 @@ function getRuntimeEnv(
290293
// Node.js v8 runtime uses FUNCTION_NAME, v10 — FUNCTION_TARGET
291294
// See: https://cloud.google.com/functions/docs/env-var#environment_variables_set_automatically
292295
functionName: process.env.FUNCTION_NAME || process.env.FUNCTION_TARGET,
293-
extensionId
296+
extensionId,
294297
}
295298
}
296299

@@ -326,7 +329,7 @@ function dummyHandler(
326329
if (options?.timeout) runtimeOptions.timeoutSeconds = options.timeout
327330

328331
return functions
329-
.runWith(runtimeOptions)
332+
.runWith(getRuntimeOptions(options))
330333
.region(options.region || defaultRegion)
331334
.https.onRequest((_req, resp) => {
332335
resp.end()
@@ -336,3 +339,24 @@ function dummyHandler(
336339
function prettyJSON(obj: any) {
337340
return JSON.stringify(obj, null, 2)
338341
}
342+
343+
/**
344+
*
345+
* @param agentOptions - TODO
346+
* @returns
347+
*/
348+
function getRuntimeOptions(
349+
agentOptions: AgentOptions | undefined
350+
): functions.RuntimeOptions {
351+
const options: functions.RuntimeOptions = {
352+
// Always assign timeout to runtime options. Unless the user defines
353+
// a custom timeout, we want to use the default timeout of 9 minutes,
354+
// to make sure the user backups are completed regardless of how many
355+
// there are.
356+
timeoutSeconds: agentOptions?.timeout || defaultTimeout,
357+
}
358+
359+
if (agentOptions?.memory) options.memory = agentOptions.memory
360+
361+
return options
362+
}

src/options.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
export const defaultControllerDomain = 'backupfire.dev'
2+
3+
export const defaultRegion = 'us-central1'
4+
5+
/**
6+
* The default function timeout - 9 minutes. It ensures that the user backups
7+
* are completed regardless of how many there are.
8+
*
9+
* Unlike the memory runtime option, timeout doesn't affect the function
10+
* instance price, so it's safe to set it to max.
11+
*/
12+
export const defaultTimeout = 540
13+
14+
/**
15+
* The default function memory. With the increased timeout, it ensures
16+
* the users' backup completion.
17+
*
18+
* Internal testing shows that 1GB is the sweet spot. It's still cheap to run
19+
* and gives room to process huge backups.
20+
*/
21+
export const defaultMemory = '1GB'

0 commit comments

Comments
 (0)