mirror of
https://github.com/hcengineering/platform.git
synced 2026-09-10 03:37:43 +02:00
Update sanity DB restore (#2836)
Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
@@ -70,4 +70,6 @@ function prepareTools (): {
|
||||
return { ...prepareToolsRaw(builder(enabled, disabled).getTxes()), version, migrateOperations }
|
||||
}
|
||||
|
||||
console.log(`tools git_version: ${process.env.GIT_REVISION ?? ''} model_version: ${process.env.MODEL_VERSION ?? ''}`)
|
||||
|
||||
devTool(prepareTools, '')
|
||||
|
||||
+1
-46
@@ -45,7 +45,7 @@ import toolPlugin from '@hcengineering/server-tool'
|
||||
import { program } from 'commander'
|
||||
import { Db, MongoClient } from 'mongodb'
|
||||
import { clearTelegramHistory } from './telegram'
|
||||
import { diffWorkspace, dumpWorkspace, restoreWorkspace } from './workspace'
|
||||
import { diffWorkspace } from './workspace'
|
||||
|
||||
import { Data, getWorkspaceId, Tx, Version } from '@hcengineering/core'
|
||||
import { MinioService } from '@hcengineering/minio'
|
||||
@@ -54,7 +54,6 @@ import { openAIConfigDefaults } from '@hcengineering/openai'
|
||||
import { benchmark } from './benchmark'
|
||||
import { cleanArchivedSpaces, cleanRemovedTransactions, cleanWorkspace } from './clean'
|
||||
import { changeConfiguration } from './configuration'
|
||||
import { rebuildElastic } from './elastic'
|
||||
import { openAIConfig } from './openai'
|
||||
|
||||
/**
|
||||
@@ -293,14 +292,6 @@ export function devTool (
|
||||
})
|
||||
})
|
||||
|
||||
program
|
||||
.command('dump-workspace <workspace> <dirName>')
|
||||
.description('dump workspace transactions and minio resources')
|
||||
.action(async (workspace: string, dirName: string, cmd) => {
|
||||
const { mongodbUri, minio } = prepareTools()
|
||||
return await dumpWorkspace(mongodbUri, getWorkspaceId(workspace, productId), dirName, minio)
|
||||
})
|
||||
|
||||
program
|
||||
.command('backup <dirName> <workspace>')
|
||||
.description('dump workspace transactions and minio resources')
|
||||
@@ -360,23 +351,6 @@ export function devTool (
|
||||
return await backupList(storage)
|
||||
})
|
||||
|
||||
program
|
||||
.command('restore-workspace <workspace> <dirName>')
|
||||
.description('restore workspace transactions and minio resources from previous dump.')
|
||||
.action(async (workspace: string, dirName: string, cmd) => {
|
||||
const { mongodbUri, minio, txes, migrateOperations } = prepareTools()
|
||||
return await restoreWorkspace(
|
||||
mongodbUri,
|
||||
getWorkspaceId(workspace, productId),
|
||||
dirName,
|
||||
minio,
|
||||
getElasticUrl(),
|
||||
transactorUrl,
|
||||
txes,
|
||||
migrateOperations
|
||||
)
|
||||
})
|
||||
|
||||
program
|
||||
.command('confirm-email <email>')
|
||||
.description('confirm user email')
|
||||
@@ -434,25 +408,6 @@ export function devTool (
|
||||
})
|
||||
})
|
||||
|
||||
program
|
||||
.command('rebuild-elastic [workspace]')
|
||||
.description('rebuild elastic index')
|
||||
.action(async (workspace: string, cmd) => {
|
||||
const { mongodbUri, minio } = prepareTools()
|
||||
return await withDatabase(mongodbUri, async (db) => {
|
||||
if (workspace === undefined) {
|
||||
const workspaces = await listWorkspaces(db, productId)
|
||||
|
||||
for (const w of workspaces) {
|
||||
await rebuildElastic(mongodbUri, getWorkspaceId(w.workspace, productId), minio, getElasticUrl())
|
||||
}
|
||||
} else {
|
||||
await rebuildElastic(mongodbUri, getWorkspaceId(workspace, productId), minio, getElasticUrl())
|
||||
console.log('rebuild end')
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
program
|
||||
.command('generate-token <name> <workspace> <productId>')
|
||||
.description('generate token')
|
||||
|
||||
+1
-146
@@ -16,155 +16,10 @@
|
||||
|
||||
import contact from '@hcengineering/contact'
|
||||
import core, { DOMAIN_TX, Tx, WorkspaceId } from '@hcengineering/core'
|
||||
import { MinioService, MinioWorkspaceItem } from '@hcengineering/minio'
|
||||
import { MigrateOperation } from '@hcengineering/model'
|
||||
import { getWorkspaceDB } from '@hcengineering/mongo'
|
||||
import { upgradeModel } from '@hcengineering/server-tool'
|
||||
import { existsSync } from 'fs'
|
||||
import { mkdir, open, readFile, writeFile } from 'fs/promises'
|
||||
import { Document, MongoClient } from 'mongodb'
|
||||
import { join } from 'path'
|
||||
import { rebuildElastic } from './elastic'
|
||||
import { MongoClient } from 'mongodb'
|
||||
import { generateModelDiff, printDiff } from './mdiff'
|
||||
|
||||
interface CollectionInfo {
|
||||
name: string
|
||||
file: string
|
||||
}
|
||||
|
||||
interface WorkspaceInfo {
|
||||
version: string
|
||||
collections: CollectionInfo[]
|
||||
minioData: MinioWorkspaceItem[]
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export async function dumpWorkspace (
|
||||
mongoUrl: string,
|
||||
workspaceId: WorkspaceId,
|
||||
fileName: string,
|
||||
minio: MinioService
|
||||
): Promise<void> {
|
||||
const client = new MongoClient(mongoUrl)
|
||||
try {
|
||||
await client.connect()
|
||||
const db = getWorkspaceDB(client, workspaceId)
|
||||
|
||||
console.log('dumping transactions...')
|
||||
|
||||
if (!existsSync(fileName)) {
|
||||
await mkdir(fileName, { recursive: true })
|
||||
}
|
||||
|
||||
const workspaceInfo: WorkspaceInfo = {
|
||||
version: '0.0.0',
|
||||
collections: [],
|
||||
minioData: []
|
||||
}
|
||||
const collections = await db.collections()
|
||||
for (const c of collections) {
|
||||
const docs = await c.find().toArray()
|
||||
workspaceInfo.collections.push({ name: c.collectionName, file: c.collectionName + '.json' })
|
||||
await writeFile(fileName + c.collectionName + '.json', JSON.stringify(docs, undefined, 2))
|
||||
}
|
||||
|
||||
console.log('Dump minio objects')
|
||||
if (await minio.exists(workspaceId)) {
|
||||
workspaceInfo.minioData.push(...(await minio.list(workspaceId)))
|
||||
const minioDbLocation = fileName + '.minio'
|
||||
if (!existsSync(minioDbLocation)) {
|
||||
await mkdir(minioDbLocation)
|
||||
}
|
||||
for (const d of workspaceInfo.minioData) {
|
||||
const stat = await minio.stat(workspaceId, d.name)
|
||||
d.metaData = stat.metaData
|
||||
|
||||
const fileHandle = await open(join(minioDbLocation, d.name), 'w')
|
||||
|
||||
const chunks: Buffer[] = await minio.read(workspaceId, d.name)
|
||||
for (const b of chunks) {
|
||||
await fileHandle.write(b)
|
||||
}
|
||||
await fileHandle.close()
|
||||
}
|
||||
}
|
||||
|
||||
await writeFile(fileName + '.workspace.json', JSON.stringify(workspaceInfo, undefined, 2))
|
||||
} finally {
|
||||
await client.close()
|
||||
}
|
||||
}
|
||||
|
||||
export async function restoreWorkspace (
|
||||
mongoUrl: string,
|
||||
workspaceId: WorkspaceId,
|
||||
fileName: string,
|
||||
minio: MinioService,
|
||||
elasticUrl: string,
|
||||
transactorUrl: string,
|
||||
rawTxes: Tx[],
|
||||
migrateOperations: [string, MigrateOperation][]
|
||||
): Promise<void> {
|
||||
console.log('Restoring workspace', mongoUrl, workspaceId, fileName)
|
||||
const client = new MongoClient(mongoUrl)
|
||||
try {
|
||||
await client.connect()
|
||||
const db = getWorkspaceDB(client, workspaceId)
|
||||
|
||||
const workspaceInfo = JSON.parse((await readFile(fileName + '.workspace.json')).toString()) as WorkspaceInfo
|
||||
|
||||
// Drop existing collections
|
||||
|
||||
const cols = await db.collections()
|
||||
for (const c of cols) {
|
||||
console.log('dropping existing table', c.collectionName)
|
||||
await db.dropCollection(c.collectionName)
|
||||
}
|
||||
// Restore collections.
|
||||
for (const c of workspaceInfo.collections) {
|
||||
const collection = db.collection(c.name)
|
||||
await collection.deleteMany({})
|
||||
const data = JSON.parse((await readFile(fileName + c.name + '.json')).toString()) as Document[]
|
||||
if (data.length > 0) {
|
||||
console.log('restore existing collection', c.name, data.length)
|
||||
await collection.insertMany(data)
|
||||
}
|
||||
}
|
||||
|
||||
if (await minio.exists(workspaceId)) {
|
||||
const objectNames = (await minio.list(workspaceId)).map((i) => i.name)
|
||||
await minio.remove(workspaceId, objectNames)
|
||||
await minio.delete(workspaceId)
|
||||
}
|
||||
await minio.make(workspaceId)
|
||||
|
||||
const minioDbLocation = fileName + '.minio'
|
||||
console.log('Restore minio objects', workspaceInfo.minioData.length)
|
||||
let promises: Promise<void>[] = []
|
||||
for (const d of workspaceInfo.minioData) {
|
||||
const file = await open(join(minioDbLocation, d.name), 'r')
|
||||
const stream = file.createReadStream()
|
||||
promises.push(
|
||||
minio.put(workspaceId, d.name, stream, d.size, d.metaData).then(async () => {
|
||||
await file.close()
|
||||
})
|
||||
)
|
||||
if (promises.length > 10) {
|
||||
await Promise.all(promises)
|
||||
promises = []
|
||||
}
|
||||
}
|
||||
|
||||
await upgradeModel(transactorUrl, workspaceId, rawTxes, migrateOperations)
|
||||
|
||||
await rebuildElastic(mongoUrl, workspaceId, minio, elasticUrl)
|
||||
} finally {
|
||||
await client.close()
|
||||
}
|
||||
}
|
||||
|
||||
export async function diffWorkspace (mongoUrl: string, workspace: WorkspaceId, rawTxes: Tx[]): Promise<void> {
|
||||
const client = new MongoClient(mongoUrl)
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user