chore(utils): Soft delete should allow self referencing circular deps (#6504)
**What** Self referencing circular dep should not be an error and should be accepted
This commit is contained in:
committed by
GitHub
parent
d983329481
commit
56cbf88115
@@ -189,6 +189,42 @@ class DeepRecursiveEntity4 {
|
||||
entity1: DeepRecursiveEntity1
|
||||
}
|
||||
|
||||
// Internal circular dependency
|
||||
|
||||
@Entity()
|
||||
class InternalCircularDependencyEntity1 {
|
||||
constructor(props: {
|
||||
id: string
|
||||
deleted_at: Date | null
|
||||
parent?: InternalCircularDependencyEntity1
|
||||
}) {
|
||||
this.id = props.id
|
||||
this.deleted_at = props.deleted_at
|
||||
|
||||
if (props.parent) {
|
||||
this.parent = props.parent
|
||||
}
|
||||
}
|
||||
|
||||
@PrimaryKey()
|
||||
id: string
|
||||
|
||||
@Property()
|
||||
deleted_at: Date | null
|
||||
|
||||
@OneToMany(
|
||||
() => InternalCircularDependencyEntity1,
|
||||
(entity) => entity.parent,
|
||||
{
|
||||
cascade: ["soft-remove"] as any,
|
||||
}
|
||||
)
|
||||
children = new Collection<InternalCircularDependencyEntity1>(this)
|
||||
|
||||
@ManyToOne(() => InternalCircularDependencyEntity1)
|
||||
parent: InternalCircularDependencyEntity1
|
||||
}
|
||||
|
||||
export {
|
||||
RecursiveEntity1,
|
||||
RecursiveEntity2,
|
||||
@@ -198,4 +234,5 @@ export {
|
||||
DeepRecursiveEntity2,
|
||||
DeepRecursiveEntity3,
|
||||
DeepRecursiveEntity4,
|
||||
InternalCircularDependencyEntity1,
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
DeepRecursiveEntity4,
|
||||
Entity1,
|
||||
Entity2,
|
||||
InternalCircularDependencyEntity1,
|
||||
RecursiveEntity1,
|
||||
RecursiveEntity2,
|
||||
} from "../__fixtures__/utils"
|
||||
@@ -38,6 +39,7 @@ describe("mikroOrmUpdateDeletedAtRecursively", () => {
|
||||
DeepRecursiveEntity2,
|
||||
DeepRecursiveEntity3,
|
||||
DeepRecursiveEntity4,
|
||||
InternalCircularDependencyEntity1,
|
||||
],
|
||||
dbName: "test",
|
||||
type: "postgresql",
|
||||
@@ -65,6 +67,26 @@ describe("mikroOrmUpdateDeletedAtRecursively", () => {
|
||||
expect(entity2.deleted_at).toEqual(deletedAt)
|
||||
})
|
||||
|
||||
it("should successfully mark the entities deleted_at recursively with internal parent/child relation", async () => {
|
||||
const manager = orm.em.fork() as SqlEntityManager
|
||||
const entity1 = new InternalCircularDependencyEntity1({
|
||||
id: "1",
|
||||
deleted_at: null,
|
||||
})
|
||||
|
||||
const childEntity1 = new InternalCircularDependencyEntity1({
|
||||
id: "2",
|
||||
deleted_at: null,
|
||||
parent: entity1,
|
||||
})
|
||||
|
||||
const deletedAt = new Date()
|
||||
await mikroOrmUpdateDeletedAtRecursively(manager, [entity1], deletedAt)
|
||||
|
||||
expect(entity1.deleted_at).toEqual(deletedAt)
|
||||
expect(childEntity1.deleted_at).toEqual(deletedAt)
|
||||
})
|
||||
|
||||
it("should throw an error when a circular dependency is detected", async () => {
|
||||
const manager = orm.em.fork() as SqlEntityManager
|
||||
const entity1 = new RecursiveEntity1({ id: "1", deleted_at: null })
|
||||
|
||||
@@ -5,8 +5,13 @@ import { SqlEntityManager } from "@mikro-orm/postgresql"
|
||||
function detectCircularDependency(
|
||||
manager: SqlEntityManager,
|
||||
entityMetadata: EntityMetadata,
|
||||
visited: Set<string> = new Set()
|
||||
visited: Set<string> = new Set(),
|
||||
shouldStop: boolean = false
|
||||
) {
|
||||
if (shouldStop) {
|
||||
return
|
||||
}
|
||||
|
||||
visited.add(entityMetadata.className)
|
||||
|
||||
const relations = entityMetadata.relations
|
||||
@@ -17,7 +22,9 @@ function detectCircularDependency(
|
||||
for (const relation of relationsToCascade) {
|
||||
const branchVisited = new Set(Array.from(visited))
|
||||
|
||||
if (branchVisited.has(relation.name)) {
|
||||
const isSelfCircularDependency = entityMetadata.class === relation.entity()
|
||||
|
||||
if (!isSelfCircularDependency && branchVisited.has(relation.name)) {
|
||||
const dependencies = Array.from(visited)
|
||||
dependencies.push(entityMetadata.className)
|
||||
const circularDependencyStr = dependencies.join(" -> ")
|
||||
@@ -33,7 +40,12 @@ function detectCircularDependency(
|
||||
.getMetadata()
|
||||
.get(relation.type)
|
||||
|
||||
detectCircularDependency(manager, relationEntityMetadata, branchVisited)
|
||||
detectCircularDependency(
|
||||
manager,
|
||||
relationEntityMetadata,
|
||||
branchVisited,
|
||||
isSelfCircularDependency
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,6 +94,9 @@ async function performCascadingSoftDeletion<T>(
|
||||
if (!entityRelation) {
|
||||
// Fixes the case of many to many through pivot table
|
||||
entityRelation = await retrieveEntity()
|
||||
if (!entityRelation) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
const isCollection = "toArray" in entityRelation
|
||||
@@ -94,10 +109,17 @@ async function performCascadingSoftDeletion<T>(
|
||||
}
|
||||
relationEntities = entityRelation.getItems()
|
||||
} else {
|
||||
const initializedEntityRelation = await wrap(entityRelation).init()
|
||||
const wrappedEntity = wrap(entityRelation)
|
||||
const initializedEntityRelation = wrappedEntity.isInitialized()
|
||||
? entityRelation
|
||||
: await wrap(entityRelation).init()
|
||||
relationEntities = [initializedEntityRelation]
|
||||
}
|
||||
|
||||
if (!relationEntities.length) {
|
||||
continue
|
||||
}
|
||||
|
||||
await mikroOrmUpdateDeletedAtRecursively(manager, relationEntities, value)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user