Problem/Motivation
On the revision tab of the host entity, a revision can be deleted.
As we are creating new revisions in sync, we can also delete a revision.
This is also needed to have garbage collection work:
Deleting a composite entity if no more referenced can only work if there is no remaining revision pointing to it.
Related #2771519: support host delete
Comments
Comment #2
jmuzz commentedComment #5
jmuzz commentedComment #7
ModernMantra commentedComment #9
miro_dietikerWe can not propagate a delete as long as we have no guarantee that new revisions are created in sync.
So IMHO this means, we should postpone this issue to #2801321: New host revisions do not always create new composite entity revisions
And if we do so after we fixed the revision creation of composites, what will be the impact on data that has been written before?
I think the problem only happened when creating records through API. It means if a user created new host revisions through API and later deletes a host revision, a composite revision might be deleted that could cause loss of a paragraph in some other revision.
Can we document this problem as known limitation?
Comment #10
berdirWe'll need to do a query to ensure that a revision is unused. We'll also need to make sure it is not the default revision and other things.
I just told @ModernMantra to extract the relevant parts from the other issue and post failing patches so we have a starting point.
Comment #11
tduong commentedTried to understand/get/extract the right "relevant parts from the other issue". Not sure if I'm doing it correctly.
Comment #13
berdirSame with deleting with a translatable field.
We must be very careful to not delete revisions that are still used. We now enforce that, but there will still be a lot of existing content where this is not true yet. Do an entity query with allRevision() for this specific revision, only delete if you can't find any content.
We might need to do some tricks to reproduce such a case in a test, e.g. manually update a field table to use the same revision ID multiple times.
Comment #14
tduong commentedOk, tried to reproduce the problem in the test, now it should fail (correct). Still can not figure out how to get the content revision (it is not always node ?) to compare with the field revision (not always composite_reference_target_revision_id) that is about to be deleted to check if other content revisions are referring to it. Probably need some hints.
Comment #16
berdirAs discussed, we should be doing an entity query instead, not db_select. You will need the same information, but it is available, you have the entity type and the field name and the paragraph id and revision id.
Something like \Drupal::entityQuery($entity_type_id)->condition($field_name . '.revision_id')->allRevisions()->count()->execute()
Comment #17
tduong commentedImproved entity query in deleteRevision(), but If I leave the throw exception, then the test fails. How can I catch it properly to assert that the exception is correct ?
Will continue tomorrow.
Comment #19
berdirLooks like I lost my review.
Here's a shortened version for now:
* Do not throw exceptions, just don't delete.
* The default revision test doesn't seem to make sense yet, you're not really doing anything yet. What you should do load one of old revisions, make it the default revision and save it again. Then delete the node revision pointing to it. Make sure it still exists and no exception is thrown.
* Mixing all those cases together is complicated. Make two separate tests methods for the duplicate revision and default revision logic, keep the existing one and just uncomment the assertion.
Comment #20
tduong commentedOk, separated and improved the tests and removed the exceptions.
Comment #23
tduong commentedRe-run tests since #2849136: EntityReferenceRevisionsServiceProvider should check for rest module that fixed our problem is committed.
Comment #25
berdiryou can already do this before executing the query.
docblock is always the same, expand it a bit:
Tests that composite revisions are not deleted when it is the default revision.
Tests that composite revisions if they are still in use.
those two lines should now actually happen automatically, try removing them.
this is too complicated. you load by a revision_id to then get its revisionid? that is guaranteed to be the same, so just check for $composite_original->getRevisionId() being the same.
lets also check that the second revision also still exists, just to be sure.
Comment #26
tduong commentedDone as suggested above. Also noticed that in the duplicated revision test I actually didn't check for the original composite revision, fixed it.
Comment #28
berdirLooks ok. I'm actually not a fan of storing local properties for services in tests, injection in tests is not necessary as we will never test a test. And there's a certain risk that it will cause some side effects if you do something like install a module that rebuilds the container.
Comment #30
miro_dietikerVery nice, committed. :-)