UBERF-4132: Fix unexpected delete of documents in query (#3921)

Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
Andrey Sobolev
2023-10-31 22:37:31 +07:00
committed by GitHub
parent c03f0d0417
commit 074dee811d
5 changed files with 65 additions and 11 deletions
+44 -1
View File
@@ -16,12 +16,14 @@
import core, {
DOMAIN_TX,
Data,
Ref,
SortingOrder,
Status,
TxCollectionCUD,
TxCreateDoc,
TxOperations,
TxUpdateDoc
TxUpdateDoc,
toIdMap
} from '@hcengineering/core'
import {
MigrateOperation,
@@ -227,6 +229,43 @@ async function fixRemainingTime (client: MigrationClient): Promise<void> {
)
}
async function fixParentsSpace (client: MigrationClient): Promise<void> {
while (true) {
const issues = await client.find<Issue>(
DOMAIN_TASK,
{ _class: tracker.class.Issue, 'parents.space': { $exists: false }, parents: { $exists: true, $ne: [] } },
{ limit: 1000 }
)
const parentIds: Set<Ref<Issue>> = new Set()
for (const i of issues) {
for (const p of i.parents ?? []) {
parentIds.add(p.parentId)
}
}
const parentIssues = toIdMap(
await client.find<Issue>(DOMAIN_TASK, { _class: tracker.class.Issue, _id: { $in: Array.from(parentIds) } })
)
for (const issue of issues) {
await client.update(
DOMAIN_TASK,
{ _id: issue._id },
{ parents: issue.parents.map((it) => ({ ...it, space: parentIssues.get(it.parentId)?.space ?? it.space })) }
)
}
if (issues.length === 0) {
break
}
}
await client.update(
DOMAIN_TASK,
{ _class: { $ne: tracker.class.Issue }, remainingTime: { $exists: true } },
{ $unset: { remainingTime: '' } }
)
}
async function moveIssues (client: MigrationClient): Promise<void> {
const docs = await client.find(DOMAIN_TRACKER, { _class: tracker.class.Issue })
if (docs.length > 0) {
@@ -252,6 +291,10 @@ export const trackerOperation: MigrateOperation = {
{
state: 'fixRemainingTime',
func: fixRemainingTime
},
{
state: 'fixParentsSpace',
func: fixParentsSpace
}
])
},
+3 -2
View File
@@ -897,17 +897,18 @@ export class LiveQuery extends TxProcessor implements Client {
}
private async handleDocRemove (q: Query, tx: TxRemoveDoc<Doc>): Promise<void> {
const h = this.client.getHierarchy()
if (q.result instanceof Promise) {
q.result = await q.result
}
if (
q.options?.limit !== undefined &&
q.options.limit === q.result.length &&
this.client.getHierarchy().isDerived(q._class, tx.objectClass)
h.isDerived(q._class, tx.objectClass)
) {
return await this.refresh(q)
}
const index = q.result.findIndex((p) => p._id === tx.objectId)
const index = q.result.findIndex((p) => p._id === tx.objectId && h.isDerived(p._class, tx.objectClass))
if (index > -1) {
q.result.splice(index, 1)
if (q.options?.total === true) {
@@ -377,7 +377,10 @@
subIssues: 0,
dueDate: object.dueDate,
parents: parentIssue
? [{ parentId: parentIssue._id, parentTitle: parentIssue.title }, ...parentIssue.parents]
? [
{ parentId: parentIssue._id, parentTitle: parentIssue.title, space: parentIssue.space },
...parentIssue.parents
]
: [],
reportedTime: 0,
remainingTime: 0,
@@ -422,11 +425,11 @@
}
const parents = parentIssue
? [
{ parentId: _id, parentTitle: value.title },
{ parentId: parentIssue._id, parentTitle: parentIssue.title },
{ parentId: _id, parentTitle: value.title, space: parentIssue.space },
{ parentId: parentIssue._id, parentTitle: parentIssue.title, space: parentIssue.space },
...parentIssue.parents
]
: [{ parentId: _id, parentTitle: value.title }]
: [{ parentId: _id, parentTitle: value.title, space: _space }]
await subIssuesComponent.save(parents, _id)
addNotification(
await translate(tracker.string.IssueCreated, {}, $themeStore.language),
+1
View File
@@ -290,6 +290,7 @@ export interface TimeSpendReport extends AttachedDoc {
export interface IssueParentInfo {
parentId: Ref<Issue>
parentTitle: string
space: Ref<Space>
}
/**
+10 -4
View File
@@ -226,7 +226,11 @@ export async function OnIssueUpdate (tx: Tx, control: TriggerControl): Promise<T
'childInfo.childId': removeTx.objectId
})
const res: Tx[] = []
const parents: IssueParentInfo[] = parentIssue.map((it) => ({ parentId: it._id, parentTitle: it.title }))
const parents: IssueParentInfo[] = parentIssue.map((it) => ({
parentId: it._id,
parentTitle: it.title,
space: it.space
}))
await updateIssueParentEstimations(
{
_id: removeTx.objectId,
@@ -354,7 +358,9 @@ async function doIssueUpdate (
)
const updatedParents =
newParent !== undefined ? [{ parentId: newParent._id, parentTitle: newParent.title }, ...newParent.parents] : []
newParent !== undefined
? [{ parentId: newParent._id, parentTitle: newParent.title, space: newParent.space }, ...newParent.parents]
: []
function update (issue: Issue): DocumentUpdate<Issue> {
const parentInfoIndex = issue.parents.findIndex(({ parentId }) => parentId === updateTx.objectId)
@@ -431,7 +437,7 @@ function updateIssueParentEstimations (
): void {
for (const pinfo of sourceParents) {
res.push(
control.txFactory.createTxUpdateDoc(tracker.class.Issue, issue.space, pinfo.parentId, {
control.txFactory.createTxUpdateDoc(tracker.class.Issue, pinfo.space, pinfo.parentId, {
$pull: {
childInfo: { childId: issue._id }
}
@@ -440,7 +446,7 @@ function updateIssueParentEstimations (
}
for (const pinfo of targetParents) {
res.push(
control.txFactory.createTxUpdateDoc(tracker.class.Issue, issue.space, pinfo.parentId, {
control.txFactory.createTxUpdateDoc(tracker.class.Issue, pinfo.space, pinfo.parentId, {
$push: {
childInfo: {
childId: issue._id,