fix: ignore analyzes collection in backup

This commit is contained in:
Innei
2022-01-09 15:20:41 +08:00
parent 0ecd731bbb
commit 8b47aac02e
4 changed files with 73 additions and 43 deletions

View File

@@ -18,6 +18,7 @@ async function bootstrap() {
const app = await NestFactory.create<NestFastifyApplication>(
AppModule,
fastifyApp,
{ logger: false },
)
const hosts = Origin.map((host) => new RegExp(host, 'i'))

View File

@@ -42,13 +42,13 @@ export class BackupController {
@Header('Content-Type', 'application/zip')
@HTTPDecorators.Bypass
async createNewBackup() {
const buffer = await this.cronService.backupDB({ uploadCOS: false })
if (typeof buffer == 'undefined') {
const res = await this.backupService.backup()
if (typeof res == 'undefined' || typeof res.buffer === 'undefined') {
throw new BadRequestException('请先开启在设置开启备份功能')
}
const stream = new Readable()
stream.push(buffer)
stream.push(res.buffer)
stream.push(null)
return stream
}

View File

@@ -5,22 +5,29 @@ import {
Logger,
Scope,
} from '@nestjs/common'
import { exec } from 'child_process'
import dayjs from 'dayjs'
import { existsSync, statSync } from 'fs'
import { readdir, readFile, rm, writeFile } from 'fs/promises'
import mkdirp from 'mkdirp'
import { join, resolve } from 'path'
import { Readable } from 'stream'
import { promisify } from 'util'
import { MONGO_DB } from '~/app.config'
import { BACKUP_DIR } from '~/constants/path.constant'
import { BACKUP_DIR, DATA_DIR } from '~/constants/path.constant'
import { AdminEventsGateway } from '~/processors/gateway/admin/events.gateway'
import { EventTypes } from '~/processors/gateway/events.types'
import { getFolderSize } from '~/utils/system.util'
import { ConfigsService } from '../configs/configs.service'
@Injectable({ scope: Scope.REQUEST })
export class BackupService {
private logger: Logger
constructor(private readonly adminGateway: AdminEventsGateway) {
constructor(
private readonly adminGateway: AdminEventsGateway,
private readonly configs: ConfigsService,
) {
this.logger = new Logger(BackupService.name)
}
@@ -52,6 +59,56 @@ export class BackupService {
)
}
async backup() {
const nowStr = dayjs().format('YYYY-MM-DD-HH:mm:ss')
const { backupOptions: configs } = await this.configs.waitForConfigReady()
if (!configs.enable) {
return
}
this.logger.log('--> 备份数据库中')
// 用时间格式命名文件夹
const dateDir = nowStr
const backupDirPath = join(BACKUP_DIR, dateDir)
mkdirp.sync(backupDirPath)
try {
await $`mongodump -h ${MONGO_DB.host} --port ${MONGO_DB.port} -d ${MONGO_DB.dbName} --excludeCollection analyzes -o ${backupDirPath} >/dev/null 2>&1`
// 打包 DB
await promisify(exec)(
`zip -r backup-${dateDir} mx-space/* && rm -rf mx-space`,
{
cwd: backupDirPath,
},
)
// 打包数据目录
await promisify(exec)(
`rsync -a . ./temp_copy_need --exclude temp_copy_need --exclude backup --exclude log && mv temp_copy_need backup_data && zip -r ${join(
backupDirPath,
`backup-${dateDir}`,
)} ./backup_data && rm -rf backup_data`,
{
cwd: DATA_DIR,
},
)
this.logger.log('--> 备份成功')
} catch (e) {
this.logger.error(
'--> 备份失败, 请确保已安装 zip 或 mongo-tools, mongo-tools 的版本需要与 mongod 版本一致, ' +
e.message,
)
throw e
}
const path = join(backupDirPath, 'backup-' + dateDir + '.zip')
return {
buffer: await readFile(path),
path,
}
}
async getFileStream(dirname: string) {
const path = this.checkBackupExist(dirname)
const stream = new Readable()
@@ -70,6 +127,7 @@ export class BackupService {
return path
}
// TODO 下面两个方法有重复代码
async saveTempBackupByUpload(buffer: Buffer) {
const tempDirPath = '/tmp/mx-space/backup'
const tempBackupPath = join(tempDirPath, 'backup.zip')

View File

@@ -1,25 +1,20 @@
import { forwardRef, Inject, Injectable, Logger } from '@nestjs/common'
import { Cron, CronExpression } from '@nestjs/schedule'
import { exec } from 'child_process'
import COS from 'cos-nodejs-sdk-v5'
import dayjs from 'dayjs'
import { existsSync } from 'fs'
import { readFile, rm, writeFile } from 'fs/promises'
import { rm, writeFile } from 'fs/promises'
import mkdirp from 'mkdirp'
import { InjectModel } from 'nestjs-typegoose'
import { join } from 'path'
import { promisify } from 'util'
import { $ } from 'zx'
import { MONGO_DB } from '~/app.config'
import { CronDescription } from '~/common/decorator/cron-description.decorator'
import { RedisItems, RedisKeys } from '~/constants/cache.constant'
import {
BACKUP_DIR,
LOCAL_BOT_LIST_DATA_FILE_PATH,
TEMP_DIR,
} from '~/constants/path.constant'
import { AggregateService } from '~/modules/aggregate/aggregate.service'
import { AnalyzeModel } from '~/modules/analyze/analyze.model'
import { BackupService } from '~/modules/backup/backup.service'
import { ConfigsService } from '~/modules/configs/configs.service'
import { NoteService } from '~/modules/note/note.service'
import { PageService } from '~/modules/page/page.service'
@@ -51,6 +46,8 @@ export class CronService {
@Inject(forwardRef(() => PageService))
private readonly pageService: PageService,
@Inject(forwardRef(() => SearchService))
@Inject(forwardRef(() => BackupService))
private readonly backupService: BackupService,
private readonly searchService: SearchService,
) {
this.logger = new Logger(CronService.name)
@@ -82,35 +79,11 @@ export class CronService {
@Cron(CronExpression.EVERY_DAY_AT_1AM, { name: 'backupDB' })
@CronDescription('备份 DB 并上传 COS')
async backupDB({ uploadCOS = true }: { uploadCOS?: boolean } = {}) {
const { backupOptions: configs } = await this.configs.waitForConfigReady()
if (!configs.enable) {
const backup = await this.backupService.backup()
if (!backup) {
this.logger.log('没有开启备份')
return
}
this.logger.log('--> 备份数据库中')
const dateDir = this.nowStr
const backupDirPath = join(BACKUP_DIR, dateDir)
mkdirp.sync(backupDirPath)
try {
await $`mongodump -h ${MONGO_DB.host} --port ${MONGO_DB.port} -d ${MONGO_DB.dbName} -o ${backupDirPath} >/dev/null 2>&1`
await promisify(exec)(
`zip -r backup-${dateDir} mx-space/* && rm -rf mx-space`,
{
cwd: backupDirPath,
},
)
this.logger.log('--> 备份成功')
} catch (e) {
this.logger.error(
'--> 备份失败, 请确保已安装 zip 或 mongo-tools, mongo-tools 的版本需要与 mongod 版本一致, ' +
e.message,
)
throw e
}
// 开始上传 COS
process.nextTick(async () => {
if (!uploadCOS) {
@@ -126,7 +99,7 @@ export class CronService {
) {
return
}
const backupFilePath = join(backupDirPath, 'backup-' + dateDir + '.zip')
const backupFilePath = backup.path
if (!existsSync(backupFilePath)) {
this.logger.warn('文件不存在, 无法上传到 COS')
@@ -142,7 +115,7 @@ export class CronService {
{
Bucket: backupOptions.bucket,
Region: backupOptions.region,
Key: `backup-${dateDir}.zip`,
Key: backup.path.slice(backup.path.lastIndexOf('/') + 1),
FilePath: backupFilePath,
},
(err) => {
@@ -155,8 +128,6 @@ export class CronService {
},
)
})
return readFile(join(backupDirPath, 'backup-' + dateDir + '.zip'))
}
@Cron(CronExpression.EVERY_1ST_DAY_OF_MONTH_AT_MIDNIGHT, {