Merge remote-tracking branch 'origin/feature/app-backups' into feature/backups-ui
This commit is contained in:
commit
c5744806ea
|
@ -4,8 +4,8 @@ import { publishEvent } from "../events"
|
|||
export async function appBackupRestored(backup: AppBackup) {
|
||||
const properties: AppBackupRevertEvent = {
|
||||
appId: backup.appId,
|
||||
backupName: backup.name,
|
||||
backupCreatedAt: backup.createdAt,
|
||||
backupName: backup.name!,
|
||||
backupCreatedAt: backup.timestamp,
|
||||
}
|
||||
|
||||
await publishEvent(Event.APP_BACKUP_RESTORED, properties)
|
||||
|
|
|
@ -3,6 +3,7 @@ import { objectStore, tenancy, db as dbCore } from "@budibase/backend-core"
|
|||
import { AppBackupQueueData } from "@budibase/types"
|
||||
import { exportApp } from "./exports"
|
||||
import { importApp } from "./imports"
|
||||
import { calculateBackupStats } from "../statistics"
|
||||
import { Job } from "bull"
|
||||
import fs from "fs"
|
||||
import env from "../../../environment"
|
||||
|
@ -52,26 +53,35 @@ async function exportProcessor(job: Job) {
|
|||
name = data.export!.name || `${trigger} - backup`
|
||||
const tenantId = tenancy.getTenantIDFromAppID(appId)
|
||||
await tenancy.doInTenant(tenantId, async () => {
|
||||
const createdAt = new Date().toISOString()
|
||||
const tarPath = await exportApp(appId, { tar: true })
|
||||
let filename = `${appId}/backup-${createdAt}.tar.gz`
|
||||
const devAppId = dbCore.getDevAppID(appId),
|
||||
prodAppId = dbCore.getProdAppID(appId)
|
||||
const timestamp = new Date().toISOString()
|
||||
const tarPath = await exportApp(devAppId, { tar: true })
|
||||
const contents = await calculateBackupStats(devAppId)
|
||||
let filename = `${prodAppId}/backup-${timestamp}.tar.gz`
|
||||
// add the tenant to the bucket path if backing up within a multi-tenant environment
|
||||
if (env.MULTI_TENANCY) {
|
||||
filename = `${tenantId}/${filename}`
|
||||
}
|
||||
const bucket = objectStore.ObjectStoreBuckets.BACKUPS
|
||||
const metadata = {
|
||||
appId,
|
||||
createdAt,
|
||||
appId: prodAppId,
|
||||
timestamp,
|
||||
trigger,
|
||||
name,
|
||||
contents,
|
||||
}
|
||||
await objectStore.upload({
|
||||
path: tarPath,
|
||||
type: "application/gzip",
|
||||
bucket,
|
||||
filename,
|
||||
metadata,
|
||||
metadata: {
|
||||
name,
|
||||
trigger,
|
||||
timestamp,
|
||||
appId: prodAppId,
|
||||
},
|
||||
})
|
||||
await backups.storeAppBackupMetadata(filename, metadata)
|
||||
// clear up the tarball after uploading it
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
import { context, db as dbCore } from "@budibase/backend-core"
|
||||
import {
|
||||
getDatasourceParams,
|
||||
getTableParams,
|
||||
getAutomationParams,
|
||||
getScreenParams,
|
||||
} from "../../../db/utils"
|
||||
|
||||
async function runInContext(appId: string, cb: any, db?: PouchDB.Database) {
|
||||
if (db) {
|
||||
return cb(db)
|
||||
} else {
|
||||
const devAppId = dbCore.getDevAppID(appId)
|
||||
return context.doInAppContext(devAppId, () => {
|
||||
const db = context.getAppDB()
|
||||
return cb(db)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export async function calculateDatasourceCount(
|
||||
appId: string,
|
||||
db?: PouchDB.Database
|
||||
) {
|
||||
return runInContext(
|
||||
appId,
|
||||
async (db: PouchDB.Database) => {
|
||||
const datasourceList = await db.allDocs(getDatasourceParams())
|
||||
const tableList = await db.allDocs(getTableParams())
|
||||
return datasourceList.rows.length + tableList.rows.length
|
||||
},
|
||||
db
|
||||
)
|
||||
}
|
||||
|
||||
export async function calculateAutomationCount(
|
||||
appId: string,
|
||||
db?: PouchDB.Database
|
||||
) {
|
||||
return runInContext(
|
||||
appId,
|
||||
async (db: PouchDB.Database) => {
|
||||
const automationList = await db.allDocs(getAutomationParams())
|
||||
return automationList.rows.length
|
||||
},
|
||||
db
|
||||
)
|
||||
}
|
||||
|
||||
export async function calculateScreenCount(
|
||||
appId: string,
|
||||
db?: PouchDB.Database
|
||||
) {
|
||||
return runInContext(
|
||||
appId,
|
||||
async (db: PouchDB.Database) => {
|
||||
const screenList = await db.allDocs(getScreenParams())
|
||||
return screenList.rows.length
|
||||
},
|
||||
db
|
||||
)
|
||||
}
|
||||
|
||||
export async function calculateBackupStats(appId: string) {
|
||||
return runInContext(appId, async (db: PouchDB.Database) => {
|
||||
const promises = []
|
||||
promises.push(calculateDatasourceCount(appId, db))
|
||||
promises.push(calculateAutomationCount(appId, db))
|
||||
promises.push(calculateScreenCount(appId, db))
|
||||
const responses = await Promise.all(promises)
|
||||
return {
|
||||
datasources: responses[0],
|
||||
automations: responses[1],
|
||||
screens: responses[2],
|
||||
}
|
||||
})
|
||||
}
|
|
@ -11,21 +11,23 @@ export enum AppBackupEventType {
|
|||
IMPORT = "import",
|
||||
}
|
||||
|
||||
export interface AppBackup extends Document {
|
||||
trigger: AppBackupTrigger
|
||||
name: string
|
||||
createdAt: string
|
||||
createdBy?: string
|
||||
filename: string
|
||||
export interface AppBackupMetadata {
|
||||
appId: string
|
||||
userId?: string
|
||||
contents?: {
|
||||
trigger: AppBackupTrigger
|
||||
name?: string
|
||||
createdBy?: string
|
||||
timestamp: string
|
||||
contents: {
|
||||
datasources: string[]
|
||||
screens: string[]
|
||||
automations: string[]
|
||||
}
|
||||
}
|
||||
|
||||
export interface AppBackup extends Document, AppBackupMetadata {
|
||||
filename: string
|
||||
}
|
||||
|
||||
export type AppBackupFetchOpts = {
|
||||
trigger?: AppBackupTrigger
|
||||
limit?: number
|
||||
|
@ -47,11 +49,3 @@ export interface AppBackupQueueData {
|
|||
backupId: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface AppBackupMetadata {
|
||||
appId: string
|
||||
trigger: AppBackupTrigger
|
||||
name?: string
|
||||
createdBy?: string
|
||||
createdAt: string
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue