Fix backup DB job to actually backup most things, refactor (#605)
* Make backup manually invokable and thereby testable * Add a shitload of missing stuff to our backups * Also backup follows as per James
This commit is contained in:
parent
18b8758191
commit
90d7f55c6d
|
@ -18,46 +18,63 @@
|
|||
|
||||
import * as functions from 'firebase-functions'
|
||||
import * as firestore from '@google-cloud/firestore'
|
||||
const client = new firestore.v1.FirestoreAdminClient()
|
||||
import { FirestoreAdminClient } from '@google-cloud/firestore/types/v1/firestore_admin_client'
|
||||
|
||||
const bucket = 'gs://manifold-firestore-backup'
|
||||
export const backupDbCore = async (
|
||||
client: FirestoreAdminClient,
|
||||
project: string,
|
||||
bucket: string
|
||||
) => {
|
||||
const name = client.databasePath(project, '(default)')
|
||||
const outputUriPrefix = `gs://${bucket}`
|
||||
// Leave collectionIds empty to export all collections
|
||||
// or set to a list of collection IDs to export,
|
||||
// collectionIds: ['users', 'posts']
|
||||
// NOTE: Subcollections are not backed up by default
|
||||
const collectionIds = [
|
||||
'contracts',
|
||||
'groups',
|
||||
'private-users',
|
||||
'stripe-transactions',
|
||||
'transactions',
|
||||
'users',
|
||||
'bets',
|
||||
'comments',
|
||||
'follows',
|
||||
'followers',
|
||||
'answers',
|
||||
'txns',
|
||||
'manalinks',
|
||||
'liquidity',
|
||||
'stats',
|
||||
'cache',
|
||||
'latency',
|
||||
'views',
|
||||
'notifications',
|
||||
'portfolioHistory',
|
||||
'folds',
|
||||
]
|
||||
return await client.exportDocuments({ name, outputUriPrefix, collectionIds })
|
||||
}
|
||||
|
||||
export const backupDb = functions.pubsub
|
||||
.schedule('every 24 hours')
|
||||
.onRun((_context) => {
|
||||
const projectId = process.env.GCP_PROJECT || process.env.GCLOUD_PROJECT
|
||||
if (projectId == null) {
|
||||
throw new Error('No project ID environment variable set.')
|
||||
.onRun(async (_context) => {
|
||||
try {
|
||||
const client = new firestore.v1.FirestoreAdminClient()
|
||||
const project = process.env.GCP_PROJECT || process.env.GCLOUD_PROJECT
|
||||
if (project == null) {
|
||||
throw new Error('No project ID environment variable set.')
|
||||
}
|
||||
const responses = await backupDbCore(
|
||||
client,
|
||||
project,
|
||||
'manifold-firestore-backup'
|
||||
)
|
||||
const response = responses[0]
|
||||
console.log(`Operation Name: ${response['name']}`)
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
throw new Error('Export operation failed')
|
||||
}
|
||||
const databaseName = client.databasePath(projectId, '(default)')
|
||||
|
||||
return client
|
||||
.exportDocuments({
|
||||
name: databaseName,
|
||||
outputUriPrefix: bucket,
|
||||
// Leave collectionIds empty to export all collections
|
||||
// or set to a list of collection IDs to export,
|
||||
// collectionIds: ['users', 'posts']
|
||||
// NOTE: Subcollections are not backed up by default
|
||||
collectionIds: [
|
||||
'contracts',
|
||||
'groups',
|
||||
'private-users',
|
||||
'stripe-transactions',
|
||||
'users',
|
||||
'bets',
|
||||
'comments',
|
||||
'followers',
|
||||
'answers',
|
||||
'txns',
|
||||
],
|
||||
})
|
||||
.then((responses) => {
|
||||
const response = responses[0]
|
||||
console.log(`Operation Name: ${response['name']}`)
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err)
|
||||
throw new Error('Export operation failed')
|
||||
})
|
||||
})
|
||||
|
|
16
functions/src/scripts/backup-db.ts
Normal file
16
functions/src/scripts/backup-db.ts
Normal file
|
@ -0,0 +1,16 @@
|
|||
import * as firestore from '@google-cloud/firestore'
|
||||
import { getServiceAccountCredentials } from './script-init'
|
||||
import { backupDbCore } from '../backup-db'
|
||||
|
||||
async function backupDb() {
|
||||
const credentials = getServiceAccountCredentials()
|
||||
const projectId = credentials.project_id
|
||||
const client = new firestore.v1.FirestoreAdminClient({ credentials })
|
||||
const bucket = 'manifold-firestore-backup'
|
||||
const resp = await backupDbCore(client, projectId, bucket)
|
||||
console.log(`Operation: ${resp[0]['name']}`)
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
backupDb().then(() => process.exit())
|
||||
}
|
|
@ -47,26 +47,29 @@ const getFirebaseActiveProject = (cwd: string) => {
|
|||
}
|
||||
}
|
||||
|
||||
export const initAdmin = (env?: string) => {
|
||||
export const getServiceAccountCredentials = (env?: string) => {
|
||||
env = env || getFirebaseActiveProject(process.cwd())
|
||||
if (env == null) {
|
||||
console.error(
|
||||
throw new Error(
|
||||
"Couldn't find active Firebase project; did you do `firebase use <alias>?`"
|
||||
)
|
||||
return
|
||||
}
|
||||
const envVar = `GOOGLE_APPLICATION_CREDENTIALS_${env.toUpperCase()}`
|
||||
const keyPath = process.env[envVar]
|
||||
if (keyPath == null) {
|
||||
console.error(
|
||||
throw new Error(
|
||||
`Please set the ${envVar} environment variable to contain the path to your ${env} environment key file.`
|
||||
)
|
||||
return
|
||||
}
|
||||
console.log(`Initializing connection to ${env} Firebase...`)
|
||||
/* eslint-disable-next-line @typescript-eslint/no-var-requires */
|
||||
const serviceAccount = require(keyPath)
|
||||
admin.initializeApp({
|
||||
return require(keyPath)
|
||||
}
|
||||
|
||||
export const initAdmin = (env?: string) => {
|
||||
const serviceAccount = getServiceAccountCredentials(env)
|
||||
console.log(`Initializing connection to ${serviceAccount.project_id}...`)
|
||||
return admin.initializeApp({
|
||||
projectId: serviceAccount.project_id,
|
||||
credential: admin.credential.cert(serviceAccount),
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user