mirror of
https://github.com/hcengineering/platform.git
synced 2025-05-13 19:00:09 +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 { program, type Command } from 'commander'
|
||||||
import { addControlledDocumentRank } from './qms'
|
import { addControlledDocumentRank } from './qms'
|
||||||
import { clearTelegramHistory } from './telegram'
|
import { clearTelegramHistory } from './telegram'
|
||||||
import { backupRestore, diffWorkspace, updateField } from './workspace'
|
import { backupRestore, diffWorkspace, restoreRemovedDoc, updateField } from './workspace'
|
||||||
|
|
||||||
import core, {
|
import core, {
|
||||||
AccountRole,
|
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
|
program
|
||||||
.command('add-controlled-doc-rank-mongo')
|
.command('add-controlled-doc-rank-mongo')
|
||||||
.description('add rank to controlled documents')
|
.description('add rank to controlled documents')
|
||||||
|
@ -18,6 +18,7 @@ import contact from '@hcengineering/contact'
|
|||||||
import core, {
|
import core, {
|
||||||
DOMAIN_TX,
|
DOMAIN_TX,
|
||||||
getWorkspaceId,
|
getWorkspaceId,
|
||||||
|
TxOperations,
|
||||||
type BackupClient,
|
type BackupClient,
|
||||||
type BaseWorkspaceInfo,
|
type BaseWorkspaceInfo,
|
||||||
type Class,
|
type Class,
|
||||||
@ -161,3 +162,66 @@ export async function backupRestore (
|
|||||||
await storageAdapter.close()
|
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