Ver Fonte

数据库备份与还原

lrf há 7 meses atrás
pai
commit
ba571a7cbd

+ 0 - 21
src/controller/home.controller.ts

@@ -1,30 +1,9 @@
 import { Controller, Get, Inject, Query } from '@midwayjs/core';
-import { Opera } from '../frame/dbOpera';
-import { InitSystemDataService } from '../service/initData/initSystemData.service';
-import { ExportConfigService } from '../service/exportConfig.service';
-import { ExportMissionService } from '../service/exportMission.service';
-import { AsyncExportService } from '../service/asyncExport.service';
-import { AliyunSmsService } from '../service/thirdParty/aliyunSms.service';
 @Controller('/')
 export class HomeController {
-  @Inject()
-  ec: ExportConfigService;
-  @Inject()
-  missionService: ExportMissionService;
-
-  @Inject()
-  aeService: AsyncExportService;
-  Opera = Opera;
-
-  @Inject()
-  smsService: AliyunSmsService;
 
   @Get('/')
   async home(@Query() query: object): Promise<any> {
-    // await this.ec.initData()
-    // await this.missionService.toSendMq(1);
-    // await this.aeService.execute(11);
-    // await this.smsService.send('13089419810', '2234');
     return 'starting...';
   }
   // @Get('/:method')

+ 21 - 7
src/controller/systemFunc.controller.ts

@@ -1,8 +1,9 @@
-import { Controller, Get, Inject } from '@midwayjs/core';
+import { Body, Controller, Get, Inject, Post } from '@midwayjs/core';
 import { InitSystemDataService } from '../service/initData/initSystemData.service';
 import { DataDealService } from '../service/initData/dataDeal.service';
 import { NeedAdminMiddleware } from '../middleware/needAdmin.middleware';
 import { ESService } from '../service/elasticsearch/es.service';
+import { DbBackupService } from '../service/dbBackup.service';
 
 /**所有的操作都不需要await.目前是 下达一个无监控的任务进程 */
 @Controller('/system/func', { middleware: [NeedAdminMiddleware] })
@@ -13,41 +14,54 @@ export class SystemFuncController {
   DataDeal: DataDealService;
   @Inject()
   es: ESService;
+  @Inject()
+  dbBackUp: DbBackupService;
+
+  @Post('/dbRestore', { routerName: `还原数据库` })
+  async dbRestore(@Body('path') path: string) {
+    this.dbBackUp.restore(path);
+    return 'ok'
+  }
+
+  @Get('/dbBackUp', { routerName: `备份数据库` })
+  async dbBackUpIntoJson() {
+    await this.dbBackUp.getTables();
+  }
 
   @Get('/')
   async index() {
     console.log('in');
   }
 
-  @Get('/initES')
+  @Get('/initES', { routerName: `初始化es索引及数据` })
   async initES() {
     this.es.initES();
   }
 
   /**修正导入的数据为 richText的数据 */
-  @Get('/cid')
+  @Get('/cid', { routerName: `修正数据` })
   async correctImportData() {
     this.DataDeal.correctImportData();
   }
 
   /**初始化后台目录 */
-  @Get('/ism')
+  @Get('/ism', { routerName: `初始化后台目录` })
   async initSystemMenus() {
     this.InitSystemData.initSystemMenus();
   }
 
   /**初始化用户目录 */
-  @Get('/ium')
+  @Get('/ium', { routerName: `初始化用户目录` })
   async initUserMenus() {
     this.InitSystemData.initUserMenus();
   }
   /**初始化角色数据 */
-  @Get('/ir')
+  @Get('/ir', { routerName: `初始化角色数据` })
   async initRoleData() {
     this.InitSystemData.initRoleData();
   }
   /**初始化角色的菜单(不包含管理员) */
-  @Get('/irm')
+  @Get('/irm', { routerName: `初始化角色菜单` })
   async initRoleMenus() {
     this.InitSystemData.initRoleMenus();
   }

+ 68 - 0
src/service/dbBackup.service.ts

@@ -0,0 +1,68 @@
+import { Config, Provide } from '@midwayjs/core';
+import { InjectDataSource, InjectEntityModel } from '@midwayjs/typeorm';
+import { DataSource, Repository, getCustomRepository, getManager } from 'typeorm';
+import { get, head, upperFirst } from 'lodash';
+import * as fs from 'fs';
+import * as path from 'path';
+@Provide()
+export class DbBackupService {
+  @InjectDataSource('default')
+  defaultDataSource: DataSource;
+
+  @Config('PathConfig.path')
+  filePath;
+
+  dbBackupDir = 'dbBackUp';
+
+  async getTables() {
+    console.log('to dump');
+    const entitys = this.defaultDataSource.entityMetadatas;
+    const dbBackUpPath = path.resolve(this.filePath, this.dbBackupDir);
+    const res = fs.existsSync(dbBackUpPath);
+    if (!res) {
+      fs.mkdirSync(dbBackUpPath);
+    }
+    for (const e of entitys) {
+      const tableNames = e.givenTableName;
+      const dataSql = `SELECT * from "public"."${tableNames}" ORDER BY "id" ;`;
+      const dataRes = await this.defaultDataSource.query(dataSql);
+      const fileFullPath = path.resolve(dbBackUpPath, `${tableNames}.json`);
+      fs.writeFileSync(fileFullPath, JSON.stringify(dataRes), 'utf-8');
+    }
+    console.log('dump finish');
+  }
+  /**
+   * 根据表名,找entity
+   * 有entity,通过数据源创建createQueryBuilder.对数据进行批量添加
+   * @param {string} dirPath 文件夹路径,没有就默认使用备份路径
+   */
+  async restore(dirPath?: string) {
+    console.log('to restore');
+    if (!dirPath) dirPath = path.resolve(this.filePath, this.dbBackupDir);
+    const dbBackUpPathDir = dirPath;
+    let dir = fs.readdirSync(dbBackUpPathDir);
+    dir = dir.map(i => {
+      const arr = i.split('.');
+      return head(arr);
+    });
+    for (const tableName of dir) {
+      // 清空表, 重置id;
+      const filePath = path.resolve(dbBackUpPathDir, `${tableName}.json`);
+      let datas = fs.readFileSync(filePath, 'utf-8');
+      if (datas) datas = JSON.parse(datas);
+      await this.defaultDataSource.query(`TRUNCATE TABLE "public"."${tableName}" RESTART IDENTITY RESTRICT;`);
+      await this.defaultDataSource.query(`SELECT setval('"${tableName}_id_seq"', (SELECT max(id) FROM "${tableName}"));`);
+      const entities: any = this.defaultDataSource.options.entities;
+      const entity = entities.find(f => get(f, 'name') === `${upperFirst(tableName)}`);
+      for (const i of datas) {
+        try {
+          await this.defaultDataSource.manager.createQueryBuilder().insert().into(entity).values(i).execute();
+        } catch (error) {
+          console.log(`${tableName} - ${get(i, 'id')} -  发生错误`);
+          console.log(error);
+        }
+      }
+    }
+    console.log('restore finish');
+  }
+}