UBER-476: Duplicate comment fix (#3425)

Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
Andrey Sobolev 2023-06-12 23:47:02 +07:00 committed by GitHub
parent e809a67451
commit 14b7806967
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 89 additions and 4 deletions

View File

@ -14,8 +14,21 @@
//
import attachment from '@hcengineering/attachment'
import chunter, { Comment } from '@hcengineering/chunter'
import contact from '@hcengineering/contact'
import core, { BackupClient, Client as CoreClient, DOMAIN_TX, TxOperations, WorkspaceId } from '@hcengineering/core'
import core, {
BackupClient,
Client as CoreClient,
DOMAIN_TX,
Doc,
Domain,
Ref,
TxCreateDoc,
TxOperations,
TxProcessor,
WorkspaceId,
generateId
} from '@hcengineering/core'
import { MinioService } from '@hcengineering/minio'
import { getWorkspaceDB } from '@hcengineering/mongo'
import recruit from '@hcengineering/recruit'
@ -23,6 +36,8 @@ import { connect } from '@hcengineering/server-tool'
import tracker from '@hcengineering/tracker'
import { MongoClient } from 'mongodb'
export const DOMAIN_COMMENT = 'comment' as Domain
export async function cleanWorkspace (
mongoUrl: string,
workspaceId: WorkspaceId,
@ -204,3 +219,54 @@ export async function cleanArchivedSpaces (workspaceId: WorkspaceId, transactorU
await connection.close()
}
}
export async function fixCommentDoubleIdCreate (workspaceId: WorkspaceId, transactorUrl: string): Promise<void> {
const connection = (await connect(transactorUrl, workspaceId, undefined, {
mode: 'backup'
})) as unknown as CoreClient & BackupClient
try {
const commentTxes = await connection.findAll(core.class.TxCollectionCUD, {
'tx._class': core.class.TxCreateDoc,
'tx.objectClass': chunter.class.Comment
})
const commentTxesRemoved = await connection.findAll(core.class.TxCollectionCUD, {
'tx._class': core.class.TxRemoveDoc,
'tx.objectClass': chunter.class.Comment
})
const removed = new Map(commentTxesRemoved.map((it) => [it.tx.objectId, it]))
// Do not checked removed
const objSet = new Set<Ref<Doc>>()
const oldValue = new Map<Ref<Doc>, string>()
for (const c of commentTxes) {
const cid = c.tx.objectId
if (removed.has(cid)) {
continue
}
const has = objSet.has(cid)
objSet.add(cid)
if (has) {
// We have found duplicate one, let's rename it.
const doc = TxProcessor.createDoc2Doc<Comment>(c.tx as unknown as TxCreateDoc<Comment>)
if (doc.message !== '' && doc.message.trim() !== '<p></p>') {
await connection.clean(DOMAIN_TX, [c._id])
if (oldValue.get(cid) === doc.message.trim()) {
console.log('delete tx', cid, doc.message)
} else {
oldValue.set(doc._id, doc.message)
console.log('renaming', cid, doc.message)
// Remove previous transaction.
c.tx.objectId = generateId()
doc._id = c.tx.objectId as Ref<Comment>
await connection.upload(DOMAIN_TX, [c])
// Also we need to create snapsot
await connection.upload(DOMAIN_COMMENT, [doc])
}
}
}
}
} catch (err: any) {
console.trace(err)
} finally {
await connection.close()
}
}

View File

@ -52,7 +52,7 @@ import { MinioService } from '@hcengineering/minio'
import { MigrateOperation } from '@hcengineering/model'
import { openAIConfigDefaults } from '@hcengineering/openai'
import { benchmark } from './benchmark'
import { cleanArchivedSpaces, cleanRemovedTransactions, cleanWorkspace } from './clean'
import { cleanArchivedSpaces, cleanRemovedTransactions, cleanWorkspace, fixCommentDoubleIdCreate } from './clean'
import { changeConfiguration } from './configuration'
import { openAIConfig } from './openai'
@ -455,6 +455,13 @@ export function devTool (
await cleanArchivedSpaces(getWorkspaceId(workspace, productId), transactorUrl)
})
program
.command('chunter-fix-comments <workspace>')
.description('chunter-fix-comments')
.action(async (workspace: string, cmd: any) => {
await fixCommentDoubleIdCreate(getWorkspaceId(workspace, productId), transactorUrl)
})
program
.command('configure <workspace>')
.description('clean archived spaces')

View File

@ -17,7 +17,7 @@
import { AttachmentRefInput } from '@hcengineering/attachment-resources'
import { Comment } from '@hcengineering/chunter'
import { AttachedData, Doc, generateId, Ref } from '@hcengineering/core'
import { DraftController, draftsStore, getClient } from '@hcengineering/presentation'
import { createQuery, DraftController, draftsStore, getClient } from '@hcengineering/presentation'
import { createBacklinks } from '../backlinks'
import chunter from '../plugin'
@ -40,10 +40,22 @@
let commentInputBox: AttachmentRefInput
const draftComment = shouldSaveDraft ? $draftsStore[draftKey] : undefined
let comment: CommentDraft = draftComment ?? getDefault()
let _id: Ref<Comment> = comment._id
let inputContent: string = comment.message
const createdQuery = createQuery()
$: createdQuery.query(chunter.class.Comment, { _id }, (docs) => {
if (docs.length > 0) {
// Ouch we have got comment with same id created already.
comment = getDefault()
_id = comment._id
commentInputBox.removeDraft(false)
}
})
function objectChange (object: CommentDraft, empty: any) {
if (shouldSaveDraft) {
draftController.save(object, empty)
@ -98,8 +110,8 @@
await createBacklinks(client, object._id, object._class, _id, message)
// Remove draft from Local Storage
_id = generateId()
comment = getDefault()
_id = comment._id
} catch (err) {
console.error(err)
} finally {