mirror of
https://github.com/hcengineering/platform.git
synced 2025-05-11 18:01:59 +00:00
Object restore tool (#8318)
Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
This commit is contained in:
parent
d689cff362
commit
cd97f6fd67
@ -78,7 +78,7 @@ import { buildStorageFromConfig, createStorageFromConfig, storageConfigFromEnv }
|
||||
import { program, type Command } from 'commander'
|
||||
import { addControlledDocumentRank } from './qms'
|
||||
import { clearTelegramHistory } from './telegram'
|
||||
import { backupRestore, diffWorkspace, updateField } from './workspace'
|
||||
import { backupRestore, diffWorkspace, restoreRemovedDoc, updateField } from './workspace'
|
||||
|
||||
import core, {
|
||||
AccountRole,
|
||||
@ -2296,6 +2296,15 @@ export function devTool (
|
||||
})
|
||||
})
|
||||
|
||||
program
|
||||
.command('restore-removed-doc <workspace>')
|
||||
.requiredOption('--ids <objectIds>', 'ids')
|
||||
.action(async (workspace: string, cmd: { ids: string }) => {
|
||||
const wsid = getWorkspaceId(workspace)
|
||||
const endpoint = await getTransactorEndpoint(generateToken(systemAccountEmail, wsid), 'external')
|
||||
await restoreRemovedDoc(toolCtx, wsid, endpoint, cmd.ids)
|
||||
})
|
||||
|
||||
program
|
||||
.command('add-controlled-doc-rank-mongo')
|
||||
.description('add rank to controlled documents')
|
||||
|
@ -18,6 +18,7 @@ import contact from '@hcengineering/contact'
|
||||
import core, {
|
||||
DOMAIN_TX,
|
||||
getWorkspaceId,
|
||||
TxOperations,
|
||||
type BackupClient,
|
||||
type BaseWorkspaceInfo,
|
||||
type Class,
|
||||
@ -161,3 +162,66 @@ export async function backupRestore (
|
||||
await storageAdapter.close()
|
||||
}
|
||||
}
|
||||
|
||||
export async function restoreRemovedDoc (
|
||||
ctx: MeasureContext,
|
||||
workspaceId: WorkspaceId,
|
||||
transactorUrl: string,
|
||||
idsVal: string
|
||||
): Promise<void> {
|
||||
const ids = idsVal.split(';').map((it) => it.trim()) as Ref<Doc>[]
|
||||
const connection = (await connect(transactorUrl, workspaceId, undefined, {
|
||||
mode: 'backup',
|
||||
model: 'upgrade', // Required for force all clients reload after operation will be complete.
|
||||
admin: 'true'
|
||||
})) as unknown as CoreClient & BackupClient
|
||||
try {
|
||||
for (const id of ids) {
|
||||
try {
|
||||
ctx.info('start restoring', { id })
|
||||
const ops = new TxOperations(connection, core.account.System)
|
||||
const processed = new Set<Ref<Doc>>()
|
||||
const txes = await getObjectTxesAndRelatedTxes(ctx, ops, id, processed, true)
|
||||
txes.filter((p) => p._class !== core.class.TxRemoveDoc).sort((a, b) => a.modifiedOn - b.modifiedOn)
|
||||
for (const tx of txes) {
|
||||
tx.space = core.space.DerivedTx
|
||||
await ops.tx(tx)
|
||||
}
|
||||
ctx.info('success restored', { id })
|
||||
} catch (err) {
|
||||
ctx.error('error restoring', { id, err })
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
await connection.sendForceClose()
|
||||
await connection.close()
|
||||
}
|
||||
}
|
||||
|
||||
async function getObjectTxesAndRelatedTxes (
|
||||
ctx: MeasureContext,
|
||||
client: TxOperations,
|
||||
objectId: Ref<Doc>,
|
||||
processed: Set<Ref<Doc>>,
|
||||
filterRemoved = false
|
||||
): Promise<Tx[]> {
|
||||
ctx.info('Find txes for', { objectId })
|
||||
const result: Tx[] = []
|
||||
if (processed.has(objectId)) {
|
||||
return result
|
||||
}
|
||||
processed.add(objectId)
|
||||
let txes = (await client.findAll(core.class.TxCUD, { objectId })) as Tx[]
|
||||
if (filterRemoved) {
|
||||
txes = txes.filter((it) => it._class !== core.class.TxRemoveDoc)
|
||||
}
|
||||
result.push(...txes)
|
||||
const relatedTxes = await client.findAll(core.class.TxCUD, { attachedTo: objectId })
|
||||
result.push(...relatedTxes)
|
||||
const relatedIds = new Set(relatedTxes.map((it) => it.objectId))
|
||||
for (const relatedId of relatedIds) {
|
||||
const rel = await getObjectTxesAndRelatedTxes(ctx, client, relatedId, processed)
|
||||
result.push(...rel)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user