mirror of
https://github.com/hcengineering/platform.git
synced 2025-04-23 08:48:01 +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 MeasureContext,
|
||||||
type Ref,
|
type Ref,
|
||||||
type TxCreateDoc,
|
type TxCreateDoc,
|
||||||
|
type TxUpdateDoc,
|
||||||
type WorkspaceId,
|
type WorkspaceId,
|
||||||
DOMAIN_TX,
|
DOMAIN_TX,
|
||||||
|
SortingOrder,
|
||||||
makeCollabYdocId,
|
makeCollabYdocId,
|
||||||
makeDocCollabId
|
makeDocCollabId
|
||||||
} from '@hcengineering/core'
|
} from '@hcengineering/core'
|
||||||
@ -63,13 +65,18 @@ export async function restoreWikiContentMongo (
|
|||||||
}
|
}
|
||||||
|
|
||||||
const correctCollabId = { objectClass: doc._class, objectId: doc._id, objectAttr: 'content' }
|
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
|
if (stat === undefined) continue
|
||||||
|
|
||||||
const ydoc1 = await loadCollabYdoc(ctx, storageAdapter, workspaceId, correctCollabId)
|
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')) {
|
if (ydoc1 !== undefined && ydoc1.share.has('content')) {
|
||||||
// There already is content, we should skip the document
|
// 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 {
|
export interface RestoreControlledDocContentParams {
|
||||||
dryRun: boolean
|
dryRun: boolean
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
import type { Class, MarkupBlobRef, Doc, Ref } from './classes'
|
import type { Blob, Class, Doc, MarkupBlobRef, Ref } from './classes'
|
||||||
|
|
||||||
/** @public */
|
/** @public */
|
||||||
export interface CollaborativeDoc {
|
export interface CollaborativeDoc {
|
||||||
@ -40,9 +40,9 @@ export function makeDocCollabId<T extends Doc, U extends keyof T> (
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @public */
|
/** @public */
|
||||||
export function makeCollabYdocId (doc: CollaborativeDoc): MarkupBlobRef {
|
export function makeCollabYdocId (doc: CollaborativeDoc): Ref<Blob> {
|
||||||
const { objectId, objectAttr } = doc
|
const { objectId, objectAttr } = doc
|
||||||
return `${objectId}%${objectAttr}` as MarkupBlobRef
|
return `${objectId}%${objectAttr}` as Ref<Blob>
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @public */
|
/** @public */
|
||||||
|
@ -19,6 +19,7 @@ import {
|
|||||||
type Ref,
|
type Ref,
|
||||||
type WorkspaceId,
|
type WorkspaceId,
|
||||||
Markup,
|
Markup,
|
||||||
|
MarkupBlobRef,
|
||||||
MeasureContext,
|
MeasureContext,
|
||||||
generateId,
|
generateId,
|
||||||
makeCollabJsonId,
|
makeCollabJsonId,
|
||||||
@ -35,9 +36,9 @@ export async function loadCollabYdoc (
|
|||||||
ctx: MeasureContext,
|
ctx: MeasureContext,
|
||||||
storageAdapter: StorageAdapter,
|
storageAdapter: StorageAdapter,
|
||||||
workspace: WorkspaceId,
|
workspace: WorkspaceId,
|
||||||
doc: CollaborativeDoc
|
doc: CollaborativeDoc | MarkupBlobRef
|
||||||
): Promise<YDoc | undefined> {
|
): Promise<YDoc | undefined> {
|
||||||
const blobId = makeCollabYdocId(doc)
|
const blobId = typeof doc === 'string' ? doc : makeCollabYdocId(doc)
|
||||||
|
|
||||||
const blob = await storageAdapter.stat(ctx, workspace, blobId)
|
const blob = await storageAdapter.stat(ctx, workspace, blobId)
|
||||||
if (blob === undefined) {
|
if (blob === undefined) {
|
||||||
@ -61,10 +62,10 @@ export async function saveCollabYdoc (
|
|||||||
ctx: MeasureContext,
|
ctx: MeasureContext,
|
||||||
storageAdapter: StorageAdapter,
|
storageAdapter: StorageAdapter,
|
||||||
workspace: WorkspaceId,
|
workspace: WorkspaceId,
|
||||||
doc: CollaborativeDoc,
|
doc: CollaborativeDoc | MarkupBlobRef,
|
||||||
ydoc: YDoc
|
ydoc: YDoc
|
||||||
): Promise<Ref<Blob>> {
|
): Promise<Ref<Blob>> {
|
||||||
const blobId = makeCollabYdocId(doc)
|
const blobId = typeof doc === 'string' ? doc : makeCollabYdocId(doc)
|
||||||
|
|
||||||
const buffer = yDocToBuffer(ydoc)
|
const buffer = yDocToBuffer(ydoc)
|
||||||
await storageAdapter.put(ctx, workspace, blobId, buffer, 'application/ydoc', buffer.length)
|
await storageAdapter.put(ctx, workspace, blobId, buffer, 'application/ydoc', buffer.length)
|
||||||
|
@ -307,9 +307,11 @@ export class S3Service implements StorageAdapter {
|
|||||||
version: result.VersionId ?? null
|
version: result.VersionId ?? null
|
||||||
}
|
}
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
|
if (err?.$metadata?.httpStatusCode !== 404) {
|
||||||
ctx.warn('no object found', { error: err, objectName, workspaceId: workspaceId.name })
|
ctx.warn('no object found', { error: err, objectName, workspaceId: workspaceId.name })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@withContext('get')
|
@withContext('get')
|
||||||
async get (ctx: MeasureContext, workspaceId: WorkspaceId, objectName: string): Promise<Readable> {
|
async get (ctx: MeasureContext, workspaceId: WorkspaceId, objectName: string): Promise<Readable> {
|
||||||
|
Loading…
Reference in New Issue
Block a user