mirror of
https://github.com/hcengineering/platform.git
synced 2025-04-13 19:58:09 +00:00
fix: restore wiki content fixes (#7474)
This commit is contained in:
parent
9994ffedc2
commit
413da21b50
@ -20,8 +20,10 @@ import core, {
|
||||
type MeasureContext,
|
||||
type Ref,
|
||||
type TxCreateDoc,
|
||||
type TxUpdateDoc,
|
||||
type WorkspaceId,
|
||||
DOMAIN_TX,
|
||||
SortingOrder,
|
||||
makeCollabYdocId,
|
||||
makeDocCollabId
|
||||
} from '@hcengineering/core'
|
||||
@ -63,13 +65,18 @@ export async function restoreWikiContentMongo (
|
||||
}
|
||||
|
||||
const correctCollabId = { objectClass: doc._class, objectId: doc._id, objectAttr: 'content' }
|
||||
const wrongCollabId = { objectClass: doc._class, objectId: doc._id, objectAttr: 'description' }
|
||||
|
||||
const stat = storageAdapter.stat(ctx, workspaceId, makeCollabYdocId(wrongCollabId))
|
||||
const wrongYdocId = await findWikiDocYdocName(ctx, db, workspaceId, doc._id)
|
||||
if (wrongYdocId === undefined) {
|
||||
console.log('current ydoc not found', doc._id)
|
||||
continue
|
||||
}
|
||||
|
||||
const stat = storageAdapter.stat(ctx, workspaceId, wrongYdocId)
|
||||
if (stat === undefined) continue
|
||||
|
||||
const ydoc1 = await loadCollabYdoc(ctx, storageAdapter, workspaceId, correctCollabId)
|
||||
const ydoc2 = await loadCollabYdoc(ctx, storageAdapter, workspaceId, wrongCollabId)
|
||||
const ydoc2 = await loadCollabYdoc(ctx, storageAdapter, workspaceId, wrongYdocId)
|
||||
|
||||
if (ydoc1 !== undefined && ydoc1.share.has('content')) {
|
||||
// There already is content, we should skip the document
|
||||
@ -101,6 +108,81 @@ export async function restoreWikiContentMongo (
|
||||
}
|
||||
}
|
||||
|
||||
export async function findWikiDocYdocName (
|
||||
ctx: MeasureContext,
|
||||
db: Db,
|
||||
workspaceId: WorkspaceId,
|
||||
doc: Ref<Document>
|
||||
): Promise<Ref<Blob> | undefined> {
|
||||
const updateContentTx = await db.collection<TxUpdateDoc<Document & { content: string }>>(DOMAIN_TX).findOne(
|
||||
{
|
||||
_class: core.class.TxUpdateDoc,
|
||||
objectId: doc,
|
||||
objectClass: document.class.Document,
|
||||
'operations.content': { $exists: true }
|
||||
},
|
||||
{
|
||||
sort: { modifiedOn: SortingOrder.Descending }
|
||||
}
|
||||
)
|
||||
|
||||
if (updateContentTx?.operations?.content != null) {
|
||||
const value = updateContentTx.operations.content as string
|
||||
if (value.includes(':')) {
|
||||
console.log('found update content tx', doc, value)
|
||||
return value.split(':')[0] as Ref<Blob>
|
||||
}
|
||||
}
|
||||
|
||||
const updateDescriptionTx = await db.collection<TxUpdateDoc<Document & { description: string }>>(DOMAIN_TX).findOne(
|
||||
{
|
||||
_class: core.class.TxUpdateDoc,
|
||||
objectId: doc,
|
||||
objectClass: document.class.Document,
|
||||
'operations.description': { $exists: true }
|
||||
},
|
||||
{
|
||||
sort: { modifiedOn: SortingOrder.Descending }
|
||||
}
|
||||
)
|
||||
|
||||
if (updateDescriptionTx?.operations?.description != null) {
|
||||
const value = updateDescriptionTx.operations.description
|
||||
if (value.includes(':')) {
|
||||
console.log('found update description tx', doc, value)
|
||||
return value.split(':')[0] as Ref<Blob>
|
||||
}
|
||||
}
|
||||
|
||||
const createContentTx = await db.collection<TxCreateDoc<Document & { content: string }>>(DOMAIN_TX).findOne({
|
||||
_class: core.class.TxCreateDoc,
|
||||
objectId: doc,
|
||||
objectClass: document.class.Document,
|
||||
'attributes.content': { $exists: true }
|
||||
})
|
||||
|
||||
if (createContentTx?.attributes?.content != null) {
|
||||
const value = createContentTx.attributes.content
|
||||
if (value.includes(':')) {
|
||||
console.log('found create content tx', doc, value)
|
||||
return value.split(':')[0] as Ref<Blob>
|
||||
}
|
||||
}
|
||||
|
||||
const createContentIdTx = await db.collection<TxCreateDoc<Document & { contentId: Ref<Blob> }>>(DOMAIN_TX).findOne({
|
||||
_class: core.class.TxCreateDoc,
|
||||
objectId: doc,
|
||||
objectClass: document.class.Document,
|
||||
'attributes.contentId': { $exists: true }
|
||||
})
|
||||
|
||||
if (createContentIdTx?.attributes?.contentId != null) {
|
||||
const value = createContentIdTx.attributes.contentId
|
||||
console.log('found create contentId tx', doc, value)
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
export interface RestoreControlledDocContentParams {
|
||||
dryRun: boolean
|
||||
}
|
||||
|
@ -13,7 +13,7 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import type { Class, MarkupBlobRef, Doc, Ref } from './classes'
|
||||
import type { Blob, Class, Doc, MarkupBlobRef, Ref } from './classes'
|
||||
|
||||
/** @public */
|
||||
export interface CollaborativeDoc {
|
||||
@ -40,9 +40,9 @@ export function makeDocCollabId<T extends Doc, U extends keyof T> (
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export function makeCollabYdocId (doc: CollaborativeDoc): MarkupBlobRef {
|
||||
export function makeCollabYdocId (doc: CollaborativeDoc): Ref<Blob> {
|
||||
const { objectId, objectAttr } = doc
|
||||
return `${objectId}%${objectAttr}` as MarkupBlobRef
|
||||
return `${objectId}%${objectAttr}` as Ref<Blob>
|
||||
}
|
||||
|
||||
/** @public */
|
||||
|
@ -19,6 +19,7 @@ import {
|
||||
type Ref,
|
||||
type WorkspaceId,
|
||||
Markup,
|
||||
MarkupBlobRef,
|
||||
MeasureContext,
|
||||
generateId,
|
||||
makeCollabJsonId,
|
||||
@ -35,9 +36,9 @@ export async function loadCollabYdoc (
|
||||
ctx: MeasureContext,
|
||||
storageAdapter: StorageAdapter,
|
||||
workspace: WorkspaceId,
|
||||
doc: CollaborativeDoc
|
||||
doc: CollaborativeDoc | MarkupBlobRef
|
||||
): Promise<YDoc | undefined> {
|
||||
const blobId = makeCollabYdocId(doc)
|
||||
const blobId = typeof doc === 'string' ? doc : makeCollabYdocId(doc)
|
||||
|
||||
const blob = await storageAdapter.stat(ctx, workspace, blobId)
|
||||
if (blob === undefined) {
|
||||
@ -61,10 +62,10 @@ export async function saveCollabYdoc (
|
||||
ctx: MeasureContext,
|
||||
storageAdapter: StorageAdapter,
|
||||
workspace: WorkspaceId,
|
||||
doc: CollaborativeDoc,
|
||||
doc: CollaborativeDoc | MarkupBlobRef,
|
||||
ydoc: YDoc
|
||||
): Promise<Ref<Blob>> {
|
||||
const blobId = makeCollabYdocId(doc)
|
||||
const blobId = typeof doc === 'string' ? doc : makeCollabYdocId(doc)
|
||||
|
||||
const buffer = yDocToBuffer(ydoc)
|
||||
await storageAdapter.put(ctx, workspace, blobId, buffer, 'application/ydoc', buffer.length)
|
||||
|
@ -307,7 +307,9 @@ export class S3Service implements StorageAdapter {
|
||||
version: result.VersionId ?? null
|
||||
}
|
||||
} catch (err: any) {
|
||||
ctx.warn('no object found', { error: err, objectName, workspaceId: workspaceId.name })
|
||||
if (err?.$metadata?.httpStatusCode !== 404) {
|
||||
ctx.warn('no object found', { error: err, objectName, workspaceId: workspaceId.name })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user