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

OWast’s picture

Status: Active » Needs review
StatusFileSize
new1.55 KB

I've made a stab at patching it.

Status: Needs review » Needs work

The last submitted patch, _relation-hook-entity-delete-less-destructive-1570510.patch, failed testing.

mikran’s picture

Version: 7.x-1.0-beta3 » 7.x-1.x-dev
Component: Entity API / Rules » API

Good idea! Couple of things...

    foreach($relation->endpoints[LANGUAGE_NONE] as $key => $endpoint) {
      if($endpoint['entity_id'] == $eid) {
        unset($relation->endpoints[LANGUAGE_NONE][$key]);
      }
    }

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.

OWast’s picture

Very true.

OWast’s picture

Status: Needs work » Needs review
StatusFileSize
new1.8 KB

Should be something like this then ...

Status: Needs review » Needs work

The last submitted patch, _relation-hook_entity_delete-less-destructive-1570510-5.patch, failed testing.

OWast’s picture

Status: Needs work » Needs review
StatusFileSize
new1.8 KB

Oh, that's embarrasing! Lemme try that again...

Status: Needs review » Needs work

The last submitted patch, _relation-hook_entity_delete-less-destructive-1570510-7.patch, failed testing.

OWast’s picture

Status: Needs work » Needs review
StatusFileSize
new1.8 KB

It's my first patch...

mikran’s picture

Status: Needs review » Needs work
Issue tags: +Needs tests

Thanks for patch, here's my quick review

  • Line indentations are way off on some lines, 'if', 'foreach' etc.. should include space before opening parenthesis (coding standards).
  • The rids of to be deleted relations are stored anyway so relation_delete_multiple can be used to delete all at once to reduce needed db operations.
  • It's better to user term 'valid' instead of 'legal'
  • This also needs tests.
+    foreach($relation->endpoints[LANGUAGE_NONE] as $key => $endpoint) {
+      if($endpoint['entity_id'] == $entity->eid 
+        && $endpoint['entity_type'] == $entity_type) {
+        unset($relation->endpoints[LANGUAGE_NONE][$key]);
+      }
+	}
  • There is no $entity->eid
OWast’s picture

Status: Needs work » Needs review
StatusFileSize
new1.83 KB

Thanks 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.

mikran’s picture

Status: Needs review » Needs work

tests...

mikran’s picture

Issue tags: +7.x-1.0 blocker

Marked as blocker for #1707058: Relation 7.x-1.0.

mikran’s picture

Assigned: Unassigned » mikran
mikran’s picture

Status: Needs work » Needs review
StatusFileSize
new2.64 KB
new804 bytes

Here are the tests. I had to make some changes to original patch to make it work.

mikran’s picture

Status: Needs review » Fixed

The tests_only patch above had wrong assert and thus it displays as passed. Other patch had it correctly and that's now committed.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

mikran’s picture

Status: Closed (fixed) » Needs work

As chx pointed out at irc, relation_load_multiple can be used to improve performance

mikran’s picture

Status: Needs work » Needs review
StatusFileSize
new2.79 KB

Here 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.

mikran’s picture

Issue tags: -Needs tests

changing tags

mikran’s picture

Issue tags: +Needs tests

There 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?

mikran’s picture

Issue tags: -Needs tests

pfft

OWast’s picture

Making cleanup optional seems a rational solution, if this is problematic... In most use cases the current cleanup works fine.

naught101’s picture

Status: Needs review » Needs work

Retroactive 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...

mikran’s picture

Issue tags: -7.x-1.0 blocker

I 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.

  • mikran committed 02bd63c on 8.x-1.x-der
    Issue #1570510 by OWast, mikran: Fix an issue with relations getting...
  • mikran committed 96b7381 on 8.x-1.x-der authored by OWast
    Issue #1570510 by OWast, mikran: Fix an issue with relations getting...

  • mikran committed 02bd63c on 8.x-2.x
    Issue #1570510 by OWast, mikran: Fix an issue with relations getting...
  • mikran committed 96b7381 on 8.x-2.x authored by OWast
    Issue #1570510 by OWast, mikran: Fix an issue with relations getting...