mirror of
https://github.com/hcengineering/platform.git
synced 2026-09-26 03:25:01 +02:00
Cloud collaborator refactoring (#6424)
This commit is contained in:
@@ -1,57 +0,0 @@
|
||||
//
|
||||
// Copyright © 2024 Hardcore Engineering Inc.
|
||||
//
|
||||
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License. You may
|
||||
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
//
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import { yDocBranchWithGC } from '@hcengineering/collaboration'
|
||||
import { type BranchDocumentRequest, type BranchDocumentResponse } from '@hcengineering/collaborator-client'
|
||||
import { MeasureContext } from '@hcengineering/core'
|
||||
import { applyUpdate, encodeStateAsUpdate } from 'yjs'
|
||||
import { Context } from '../../context'
|
||||
import { RpcMethodParams } from '../rpc'
|
||||
|
||||
export async function branchDocument (
|
||||
ctx: MeasureContext,
|
||||
context: Context,
|
||||
payload: BranchDocumentRequest,
|
||||
params: RpcMethodParams
|
||||
): Promise<BranchDocumentResponse> {
|
||||
const { sourceDocumentId, targetDocumentId } = payload
|
||||
const { hocuspocus } = params
|
||||
|
||||
const sourceConnection = await ctx.with('connect', { type: 'source' }, async () => {
|
||||
return await hocuspocus.openDirectConnection(sourceDocumentId, context)
|
||||
})
|
||||
|
||||
const targetConnection = await ctx.with('connect', { type: 'target' }, async () => {
|
||||
return await hocuspocus.openDirectConnection(targetDocumentId, context)
|
||||
})
|
||||
|
||||
try {
|
||||
let update = new Uint8Array()
|
||||
|
||||
await sourceConnection.transact((document) => {
|
||||
const copy = yDocBranchWithGC(document)
|
||||
update = encodeStateAsUpdate(copy)
|
||||
})
|
||||
|
||||
await targetConnection.transact((document) => {
|
||||
applyUpdate(document, update)
|
||||
})
|
||||
} finally {
|
||||
await sourceConnection.disconnect()
|
||||
await targetConnection.disconnect()
|
||||
}
|
||||
|
||||
return {}
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
//
|
||||
// Copyright © 2024 Hardcore Engineering Inc.
|
||||
//
|
||||
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License. You may
|
||||
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
//
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import { YDocVersion, takeCollaborativeDocSnapshot, yDocCopyXmlField } from '@hcengineering/collaboration'
|
||||
import { parseDocumentId, type CopyContentRequest, type CopyContentResponse } from '@hcengineering/collaborator-client'
|
||||
import { MeasureContext } from '@hcengineering/core'
|
||||
import { Doc as YDoc } from 'yjs'
|
||||
import { Context } from '../../context'
|
||||
import { RpcMethodParams } from '../rpc'
|
||||
|
||||
export async function copyContent (
|
||||
ctx: MeasureContext,
|
||||
context: Context,
|
||||
payload: CopyContentRequest,
|
||||
params: RpcMethodParams
|
||||
): Promise<CopyContentResponse> {
|
||||
const { documentId, sourceField, targetField, snapshot } = payload
|
||||
const { hocuspocus, storageAdapter } = params
|
||||
const { workspaceId } = context
|
||||
|
||||
const connection = await ctx.with('connect', {}, async () => {
|
||||
return await hocuspocus.openDirectConnection(documentId, context)
|
||||
})
|
||||
|
||||
try {
|
||||
await ctx.with('copy', {}, async () => {
|
||||
await connection.transact((document) => {
|
||||
yDocCopyXmlField(document, sourceField, targetField)
|
||||
})
|
||||
})
|
||||
|
||||
if (snapshot !== undefined && snapshot.versionId !== 'HEAD') {
|
||||
const ydoc = connection.document ?? new YDoc()
|
||||
const { collaborativeDoc } = parseDocumentId(documentId)
|
||||
|
||||
const version: YDocVersion = {
|
||||
versionId: snapshot.versionId,
|
||||
name: snapshot.versionName ?? snapshot.versionId,
|
||||
createdBy: snapshot.createdBy,
|
||||
createdOn: Date.now()
|
||||
}
|
||||
|
||||
await ctx.with('snapshot', {}, async () => {
|
||||
await takeCollaborativeDocSnapshot(storageAdapter, workspaceId, collaborativeDoc, ydoc, version, ctx)
|
||||
})
|
||||
}
|
||||
} finally {
|
||||
await connection.disconnect()
|
||||
}
|
||||
|
||||
return {}
|
||||
}
|
||||
@@ -21,10 +21,10 @@ import { RpcMethodParams } from '../rpc'
|
||||
export async function getContent (
|
||||
ctx: MeasureContext,
|
||||
context: Context,
|
||||
documentId: string,
|
||||
payload: GetContentRequest,
|
||||
params: RpcMethodParams
|
||||
): Promise<GetContentResponse> {
|
||||
const { documentId } = payload
|
||||
const { hocuspocus, transformer } = params
|
||||
|
||||
const connection = await ctx.with('connect', {}, async () => {
|
||||
|
||||
@@ -14,18 +14,10 @@
|
||||
//
|
||||
|
||||
import { getContent } from './getContent'
|
||||
import { copyContent } from './copyContent'
|
||||
import { updateContent } from './updateContent'
|
||||
import { branchDocument } from './branchDocument'
|
||||
import { removeDocument } from './removeDocument'
|
||||
import { takeSnapshot } from './takeSnapshot'
|
||||
import { RpcMethod } from '../rpc'
|
||||
|
||||
export const methods: Record<string, RpcMethod> = {
|
||||
getContent,
|
||||
copyContent,
|
||||
updateContent,
|
||||
branchDocument,
|
||||
removeDocument,
|
||||
takeSnapshot
|
||||
updateContent
|
||||
}
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
//
|
||||
// Copyright © 2024 Hardcore Engineering Inc.
|
||||
//
|
||||
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License. You may
|
||||
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
//
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import { collaborativeHistoryDocId } from '@hcengineering/collaboration'
|
||||
import {
|
||||
parseDocumentId,
|
||||
type RemoveDocumentRequest,
|
||||
type RemoveDocumentResponse
|
||||
} from '@hcengineering/collaborator-client'
|
||||
import { MeasureContext, collaborativeDocParse } from '@hcengineering/core'
|
||||
import { Context } from '../../context'
|
||||
import { RpcMethodParams } from '../rpc'
|
||||
|
||||
export async function removeDocument (
|
||||
ctx: MeasureContext,
|
||||
context: Context,
|
||||
payload: RemoveDocumentRequest,
|
||||
params: RpcMethodParams
|
||||
): Promise<RemoveDocumentResponse> {
|
||||
const { documentId } = payload
|
||||
const { hocuspocus, storageAdapter } = params
|
||||
const { workspaceId } = context
|
||||
|
||||
const document = hocuspocus.documents.get(documentId)
|
||||
if (document !== undefined) {
|
||||
hocuspocus.closeConnections(documentId)
|
||||
hocuspocus.unloadDocument(document)
|
||||
}
|
||||
|
||||
const { collaborativeDoc } = parseDocumentId(documentId)
|
||||
const { documentId: contentDocumentId } = collaborativeDocParse(collaborativeDoc)
|
||||
const historyDocumentId = collaborativeHistoryDocId(contentDocumentId)
|
||||
|
||||
try {
|
||||
await storageAdapter.remove(ctx, workspaceId, [contentDocumentId, historyDocumentId])
|
||||
} catch (err) {
|
||||
ctx.error('failed to remove document', { documentId, error: err })
|
||||
}
|
||||
|
||||
return {}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
//
|
||||
// Copyright © 2024 Hardcore Engineering Inc.
|
||||
//
|
||||
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License. You may
|
||||
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
//
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import { YDocVersion, takeCollaborativeDocSnapshot } from '@hcengineering/collaboration'
|
||||
import {
|
||||
parseDocumentId,
|
||||
type TakeSnapshotRequest,
|
||||
type TakeSnapshotResponse
|
||||
} from '@hcengineering/collaborator-client'
|
||||
import { CollaborativeDocVersionHead, MeasureContext, collaborativeDocParse } from '@hcengineering/core'
|
||||
import { Doc as YDoc } from 'yjs'
|
||||
import { Context } from '../../context'
|
||||
import { RpcMethodParams } from '../rpc'
|
||||
|
||||
export async function takeSnapshot (
|
||||
ctx: MeasureContext,
|
||||
context: Context,
|
||||
payload: TakeSnapshotRequest,
|
||||
params: RpcMethodParams
|
||||
): Promise<TakeSnapshotResponse> {
|
||||
const { documentId, snapshot } = payload
|
||||
const { hocuspocus, storageAdapter } = params
|
||||
const { workspaceId } = context
|
||||
|
||||
const version: YDocVersion = {
|
||||
versionId: snapshot.versionId,
|
||||
name: snapshot.versionName ?? snapshot.versionId,
|
||||
createdBy: snapshot.createdBy,
|
||||
createdOn: Date.now()
|
||||
}
|
||||
|
||||
const { collaborativeDoc } = parseDocumentId(documentId)
|
||||
const { versionId } = collaborativeDocParse(collaborativeDoc)
|
||||
if (versionId !== CollaborativeDocVersionHead) {
|
||||
throw new Error('invalid document version')
|
||||
}
|
||||
|
||||
const connection = await ctx.with('connect', {}, async () => {
|
||||
return await hocuspocus.openDirectConnection(documentId, context)
|
||||
})
|
||||
|
||||
try {
|
||||
const ydoc = connection.document ?? new YDoc()
|
||||
|
||||
await ctx.with('snapshot', {}, async () => {
|
||||
await takeCollaborativeDocSnapshot(storageAdapter, workspaceId, collaborativeDoc, ydoc, version, ctx)
|
||||
})
|
||||
|
||||
return { ...version }
|
||||
} finally {
|
||||
await connection.disconnect()
|
||||
}
|
||||
}
|
||||
@@ -14,25 +14,20 @@
|
||||
//
|
||||
|
||||
import { MeasureContext } from '@hcengineering/core'
|
||||
import {
|
||||
parseDocumentId,
|
||||
type UpdateContentRequest,
|
||||
type UpdateContentResponse
|
||||
} from '@hcengineering/collaborator-client'
|
||||
import { YDocVersion, takeCollaborativeDocSnapshot } from '@hcengineering/collaboration'
|
||||
import { Doc as YDoc, applyUpdate, encodeStateAsUpdate } from 'yjs'
|
||||
import { type UpdateContentRequest, type UpdateContentResponse } from '@hcengineering/collaborator-client'
|
||||
import { applyUpdate, encodeStateAsUpdate } from 'yjs'
|
||||
import { Context } from '../../context'
|
||||
import { RpcMethodParams } from '../rpc'
|
||||
|
||||
export async function updateContent (
|
||||
ctx: MeasureContext,
|
||||
context: Context,
|
||||
documentId: string,
|
||||
payload: UpdateContentRequest,
|
||||
params: RpcMethodParams
|
||||
): Promise<UpdateContentResponse> {
|
||||
const { documentId, content, snapshot } = payload
|
||||
const { hocuspocus, transformer, storageAdapter } = params
|
||||
const { workspaceId } = context
|
||||
const { content } = payload
|
||||
const { hocuspocus, transformer } = params
|
||||
|
||||
const updates = await ctx.with('transform', {}, () => {
|
||||
const updates: Record<string, Uint8Array> = {}
|
||||
@@ -41,6 +36,7 @@ export async function updateContent (
|
||||
const ydoc = transformer.toYdoc(markup, field)
|
||||
updates[field] = encodeStateAsUpdate(ydoc)
|
||||
})
|
||||
|
||||
return updates
|
||||
})
|
||||
|
||||
@@ -60,22 +56,6 @@ export async function updateContent (
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
if (snapshot !== undefined && snapshot.versionId !== 'HEAD') {
|
||||
const ydoc = connection.document ?? new YDoc()
|
||||
const { collaborativeDoc } = parseDocumentId(documentId)
|
||||
|
||||
const version: YDocVersion = {
|
||||
versionId: snapshot.versionId,
|
||||
name: snapshot.versionName ?? snapshot.versionId,
|
||||
createdBy: snapshot.createdBy,
|
||||
createdOn: Date.now()
|
||||
}
|
||||
|
||||
await ctx.with('snapshot', {}, async () => {
|
||||
await takeCollaborativeDocSnapshot(storageAdapter, workspaceId, collaborativeDoc, ydoc, version, ctx)
|
||||
})
|
||||
}
|
||||
} finally {
|
||||
await connection.disconnect()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user