Relation module invokes hook_entity_delete() to clear out relations pointing to the deleted entity. This is a good thing, but in my opinion it needs to be a little less radical.
A relation module may be of varying arity (ie. min_arity: 2, max_arity: inf), and when this kind of relation looses an entity it may still be a valid relation. Think three siblings. One of them dies. The two others should still be siblings.
I suggest that the hook instead of deleting the relation directly first strips it of its invalid endpoints and then tests if the relation is of valid arity, and deletes the relation if it isn't.
Comments
Comment #1
OWastI've made a stab at patching it.
Comment #3
mikran commentedGood idea! Couple of things...
This needs entity type condition as well, otherwise unnecessary endpoints might end up being removed. In addition to that the notification message needs to be rewritten too.
Comment #4
OWastVery true.
Comment #5
OWastShould be something like this then ...
Comment #7
OWastOh, that's embarrasing! Lemme try that again...
Comment #9
OWastIt's my first patch...
Comment #10
mikran commentedThanks for patch, here's my quick review
Comment #11
OWastThanks for that, here's those mistakes corrected. I won't be writing tests, though, as I don't have the development environment for it anymore. This came up while I was interning at a place, and I'm not there anymore.
Comment #12
mikran commentedtests...
Comment #13
mikran commentedMarked as blocker for #1707058: Relation 7.x-1.0.
Comment #14
mikran commentedComment #15
mikran commentedHere are the tests. I had to make some changes to original patch to make it work.
Comment #16
mikran commentedThe tests_only patch above had wrong assert and thus it displays as passed. Other patch had it correctly and that's now committed.
Comment #18
mikran commentedAs chx pointed out at irc, relation_load_multiple can be used to improve performance
Comment #19
mikran commentedHere is a patch that uses relation_load_multiple and just for those relations that we need to resave. A new query is in place to fetch relation arity.
I guess this needs benchmarking to figure out if we need limits and more complex processes to clean the data.
Comment #20
mikran commentedchanging tags
Comment #21
mikran commentedThere is no easy solution to this, otherwise it would've been applied to core and taxonomy term references already (#1281114: Database records not deleted for Term Reference Fields after Term is Deleted.
I prefer current functionality a lot and I think the way forward could be to just make it possible that when working with huge number of relations the API could be used without automatic cleanup and then do the cleanup some other way later on. Any thoughts on this?
Comment #22
mikran commentedpfft
Comment #23
OWastMaking cleanup optional seems a rational solution, if this is problematic... In most use cases the current cleanup works fine.
Comment #24
naught101 commentedRetroactive clean up could be a real pain though. What are you going to do, run though every row in the endpoints field data table and check and see if the entity still exists, and if not, delete it (remembering that that can't be done just in the DB, since each entity stores it's data in it's own table)? Or make a new table of "deleted entities"?
It might make sense to have some kind of per-relation-type option that decides whether relations should be cleaned up or not if an entity is delete, and they don't go below their minimum arity. That would work for the case in the original post, no? If a relation goes below it's minimum arity, then it's no longer valid, and should be deleted.
Also, because this is fairly edge-casey, I think it probably doesn't need to be a release blocker...
Comment #25
mikran commentedI agree this is not a blocker anymore.
I was thinking about using job_scheduler with deleted entity id stored there and that process could check all relations that have given endpoint and resave / delete them x at a time. But then, I don't like the idea of having dependency added to relation.