The changes tracker sometimes misses a link deletion updates
sedovalx opened this issue · 1 comments
sedovalx commented
Here is the case:
class Group(entity: Entity) : XdEntity(entity) {
companion object : XdNaturalEntityType<Group>() {
fun new() = new {
this.resource = Resource.new()
}
}
var resource by xdLink1(Resource, onDelete = OnDeletePolicy.CASCADE, onTargetDelete = OnDeletePolicy.FAIL)
override fun beforeFlush() {
super.beforeFlush()
if (hasChanges(Group::resource) && getOldValue(Group::resource) != null) {
throw RuntimeException("Can't change resource")
}
}
}
class Service(entity: Entity) : XdEntity(entity) {
companion object : XdNaturalEntityType<Service>() {
val instance by xdSingleton()
}
val resources by xdChildren0_N(Resource::service)
}
class Resource(entity: Entity) : XdEntity(entity) {
companion object : XdNaturalEntityType<Resource>() {
fun new() = new {
this.service = Service.instance
}
}
var service: Service by xdParent(Service::resources)
}
class TestCase {
@Test
fun `should throw on changing resource`() {
XdModel.registerNodes(Group, Resource, Service)
val dir = Files.createTempDirectory("xodus")
val store = StaticStoreContainer.init(dir.toFile(), "test")
initMetaData(XdModel.hierarchy, store)
val group1 = store.transactional { Group.new() }
val group2 = store.transactional { Group.new() }
assertThrows<RuntimeException> {
store.transactional {
group1.resource.delete()
group1.resource = group2.resource
}
}
}
}
The exceptions is never thrown in this case as there is no old value for the resource
property. As for the changes tracker, here is what it contains on the moment of the beforeFlush
execution:
The example above works as expected if I put the explicit resource deletion after the assignment:
group1.resource = group2.resource
group1.resource.delete()
sedovalx commented
Basically, the REMOVE
change on the Group#resource
link is not generated during the explicit deletion of the resource in case of the onTargetDelete = FAIL
link constraint.