Problem/Motivation

#2282119: Make the Entity Field API handle field purging will add support for purging base fields, which means that the purging process can be moved out of the Field module.

Proposed resolution

Move the field purging code from the Field module (field_purge.inc) to a separate service provided by Entity Field API.
The new service is FieldPurger which is a standalone class with no interface.
We also convert field.settings.purge_batch_size to Settings::get('purge_batch_size') since it is environment specific.

Remaining tasks

Review

User interface changes

N/A

API changes

API addition: a new core service FieldPurger has been added to handle the purging of deleted field data.

Data model changes

N/A

Issue fork drupal-2907780

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

amateescu created an issue. See original summary.

plach’s picture

Title: Add support for deleting bundle fields » Complete Entity Field API field purging support

Discussed this with @amateescu and we agreed to re-scope this to perform all the final clean-ups to make sure the Entity Field API is fully capable of dealing with purging of any field, flavor including non-configurable bundle fields, and get rid of any dependency on the Field module.

amateescu’s picture

Title: Complete Entity Field API field purging support » Clean up field_purge.inc
Issue summary: View changes

Deleting bundle fields has been implemented in #2282119: Make the Entity Field API handle field purging after all, so this issue is only about cleaning up field_purge.inc.

amateescu’s picture

Title: Clean up field_purge.inc » Add a field purgatory service
Issue summary: View changes
StatusFileSize
new113.95 KB
new27.94 KB

With great pride I give you.. the field purgatory! :D

amateescu’s picture

StatusFileSize
new43.62 KB
new15.68 KB

Missed a few spots :/

plach’s picture

Nice :)

  1. +++ b/core/lib/Drupal/Core/Field/FieldPurgatory.php
    @@ -0,0 +1,140 @@
    +      // We cannot purge anything if the entity type is unknown (e.g. the
    +      // providing module was uninstalled).
    +      // @todo Revisit after https://www.drupal.org/node/2080823.
    ...
    +      // We cannot purge anything if the entity type is unknown (e.g. the
    ...
    +      // @todo Revisit after https://www.drupal.org/node/2080823.
    

    Are these comments still valid? The pointed issue is closed/fixed.

  2. +++ b/core/lib/Drupal/Core/Field/FieldPurgatory.php
    @@ -0,0 +1,140 @@
    +    // Retrieve all deleted field storages. Any that have no fields can be purged.
    

    80 chars ;)

  3. +++ b/core/modules/field/tests/src/Kernel/BulkDeleteTest.php
    @@ -281,7 +281,7 @@ public function testPurgeWithDeletedAndActiveField() {
    +    \Drupal::service('entity_field.purgatory')->purgeBatch(50);
    
    @@ -326,7 +326,7 @@ public function testPurgeField() {
    +      \Drupal::service('entity_field.purgatory')->purgeBatch($batch_size);
    
    @@ -352,7 +352,7 @@ public function testPurgeField() {
    +    \Drupal::service('entity_field.purgatory')->purgeBatch($batch_size);
    
    @@ -385,7 +385,7 @@ public function testPurgeFieldStorage() {
    +    \Drupal::service('entity_field.purgatory')->purgeBatch(10);
    
    @@ -403,7 +403,7 @@ public function testPurgeFieldStorage() {
    +    \Drupal::service('entity_field.purgatory')->purgeBatch(0);
    
    @@ -422,7 +422,7 @@ public function testPurgeFieldStorage() {
    +    \Drupal::service('entity_field.purgatory')->purgeBatch(10);
    
    @@ -440,7 +440,7 @@ public function testPurgeFieldStorage() {
    +    \Drupal::service('entity_field.purgatory')->purgeBatch(0);
    
    +++ b/core/modules/field/tests/src/Kernel/FieldImportDeleteTest.php
    @@ -107,15 +107,15 @@ public function testImportDelete() {
    +    $deleted_storage_definitions = \Drupal::service('entity_field.deleted_fields_repository')->getFieldStorageDefinitions();
    ...
    +    $deleted_storage_definitions = \Drupal::service('entity_field.deleted_fields_repository')->getFieldStorageDefinitions();
    
    +++ b/core/modules/field/tests/src/Kernel/FieldImportDeleteUninstallTest.php
    @@ -150,8 +150,8 @@ public function testImportAlreadyDeletedUninstall() {
    +    $deleted_storage_definitions = \Drupal::service('entity_field.deleted_fields_repository')->getFieldStorageDefinitions();
    
    @@ -161,8 +161,8 @@ public function testImportAlreadyDeletedUninstall() {
    +    $deleted_storage_definitions = \Drupal::service('entity_field.deleted_fields_repository')->getFieldStorageDefinitions();
    
    +++ b/core/tests/Drupal/KernelTests/Core/Entity/EntityDefinitionUpdateTest.php
    @@ -444,7 +444,7 @@ public function testBaseFieldDeleteWithExistingData() {
    +    \Drupal::service('entity_field.purgatory')->purgeBatch(10);
    
    @@ -515,7 +515,7 @@ public function testBundleFieldDeleteWithExistingData() {
    +    \Drupal::service('entity_field.purgatory')->purgeBatch(10);
    

    It would be nice if we instantiated the service just once :)

cosmicdreams’s picture

Or, is it more like a Recycle bin? Where you place data before you decide it should be deleted for good.

Therefore, is this the beginning of a Trash bin in core for content?

Edit:
Well, not the beginning, as @amateescu will surely point out: https://www.drupal.org/project/trash

amateescu’s picture

@masipila, actually I implemented the ability to purge bundle fields in #2282119-42: Make the Entity Field API handle field purging, so #2906470: Orphan comments and entries in comment_entity_statistics after comment field instance has been deleted should be good to go from that POV :)

amateescu’s picture

Status: Postponed » Needs review
StatusFileSize
new44.75 KB
new6.24 KB

@yched, what can I say.. I was speechless from laughing out loud :D There are some valid concerns in there but I'm afraid we need to find someone who is more spiritual to give us a definitive answer. However, I hope your Sunday was not so bad after all ;)

@cosmicdreams, this is more like the garbage truck that already picked up your trash and it's on its way to the garbage dump. If you hurry up and you're willing to wade through the pile of trash, you might be able to recover some of the data from your deleted fields :D

@plach,

1. The @todos are useless but the comments are still valid since we can not purge the data if the entity type class is not available anymore.

2. Fixed.

3. Fixed the places where we were calling the service more than 3 times. For one or two calls.. it's not worth the effort IMO :)

cosmicdreams’s picture

If I'm understanding you correctly, this "purgatory" service is not like a trash bin because some process to delete the items in the bin is actively processing. Despite that active purging process, it is still possible to save the items, if you act strategically and quickly.

Like: https://youtu.be/QtQPmDjuA5s

If that's the case, why would we allow that saving of items that have been marked for purging and are actively being purged?

amateescu’s picture

LOL, that scene fits this whole discussion perfectly :D

Allowing deleted data to be recovered is not really something that we do on purpose. It's just that it needs to sit there until the service comes up and says "hey, I'm going to delete this piece of field data permanently, is there anyone out there who cares and wants to do something about it?". So until that happens for every piece of data, we have to keep it stashed away somewhere :)

cosmicdreams’s picture

And that description does not match a recycle bin because the directive to finally delete the data has been given and a process is actively deleting data that has already passed that system-driven check of whether something needs that data or not?

Because without that context of having a processing actively deleting data underway, what you've just described is a trash bin / recycle bin.

amateescu’s picture

Right, but that context is important because that's pretty much what field purging is about.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

dillix’s picture

Version: 8.6.x-dev » 8.5.x-dev

Will this service delete fields marked with deleted flag when base entity for this field does't exist anymore? I have 3 ghost fields marked with deleted flag, but field_cron() can't delete them because commerce changed entity name without update its fields on alpha->beta stage.

plach’s picture

Version: 8.5.x-dev » 8.6.x-dev

This kind change needs to go into the development branch first. Backport is considered afterwards.

dillix’s picture

@plach what should we do with ghost fields?

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

needs-review-queue-bot’s picture

Status: Needs review » Needs work
StatusFileSize
new132 bytes

The Needs Review Queue Bot tested this issue. It either no longer applies to Drupal core, or fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".

Apart from a re-roll or rebase, this issue may need more work to address feedback in the issue or MR comments. To progress an issue, incorporate this feedback as part of the process of updating the issue. This helps other contributors to know what is outstanding.

Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

cosmicdreams’s picture

Issue tags: +Needs reroll
karishmaamin’s picture

Status: Needs work » Needs review
StatusFileSize
new48.02 KB

Re-rolled patch against 10.1.x. Please review

tanuj.’s picture

StatusFileSize
new0 bytes
new41.73 KB

Tried to fix CCF on #33
attached interdiff file

tanuj.’s picture

StatusFileSize
new47.51 KB
new11.29 KB

added wrong patch file on #34
Tried to fix CCF on #33
attached interdiff file

nikhil_110’s picture

Issue tags: -Needs reroll
StatusFileSize
new48.2 KB
new5.82 KB

Fix CCF on #33 & Attached Interdiff file

The last submitted patch, 35: 2907780-35.patch, failed testing. View results

Status: Needs review » Needs work

The last submitted patch, 36: 2907780_34.patch, failed testing. View results

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

catch’s picture

This could use an update now that OOP hooks are in.

anmolgoyal74 made their first commit to this issue’s fork.

anmolgoyal74’s picture

Status: Needs work » Needs review
Issue tags: +DrupalCon Singapore 2024

stborchert’s picture

Issue tags: -DrupalCon Singapore 2024 +Singapore2024
anmolgoyal74’s picture

I have re-rolled the patch and used OOP hooks to purge the field definitions. I did it as a part of contribution sprint at DrupalCon Singapore 2024.

immaculatexavier’s picture

Hi @anmolgoyal74

The reroll seems to be good.


Fix PHPCS Violations:

Go through the generated PHPCS report and resolve the coding standard violations. This may involve reformatting the code, adding missing docblocks, or updating variable names.

Address PHPStan Issues:

Review the PHPStan analysis and resolve any potential type mismatches, missing variables, or logical errors.

immaculatexavier’s picture

Status: Needs review » Needs work
anmolgoyal74’s picture

Status: Needs work » Needs review
amateescu’s picture

Title: Add a field purgatory service » Add a field purger service

While this issue was quite a nice trip down memory lane, I wasn't really serious with the previous service name :)

Updated it to "field purger" and brought this old patch up to current core standards, with a change record as well: https://www.drupal.org/node/3494023

nicxvan’s picture

Went through it a couple of times.

Just one question in the mr.

smustgrave’s picture

Status: Needs review » Needs work

Comment seems valid.

Also will need test coverage for the update hook around the config updates.

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.

nicxvan’s picture

Status: Needs work » Needs review

I think this is ready for review again!

I rebased on main
I updated deprecation versions
I added a deprecation to the file itself

I'm not sure on the system update number

The only bit from the rebase was moving where the field_purge_batch was called from since that test was refactored to handle update multiple types

There is some discussion about this being postponed, but I don't see any reason to postpone this.
I took care of my comment from the other MR but it was trivial, just copying a log.

I'm not sure what test coverage updates like that usually get, do you have an example?

I also removed the require once for the purger and the outdated comment.

nicxvan changed the visibility of the branch 2907780-add-a-field to hidden.

nicxvan’s picture

I don't see any discussion about moving that config, why was it moved to system, I'm not sure we want to do that do we?

Edit: nevermind, it's because the purger service was moved to the core field subsystem.

berdir’s picture

Status: Needs review » Needs work
nicxvan’s picture

Issue summary: View changes
nicxvan’s picture

Discussed this on slack a bit, there really doesn't seem to be a need for the interface since it doesn't look like it needs to be fully swapped out.

If someone needs more they can subclass it and still override it.

nicxvan’s picture

berdir’s picture

This needs another rebase.

claudiu.cristea’s picture

Assigned: Unassigned » claudiu.cristea

Let's try to bring it to finish

andypost’s picture

summary needs to be polished and config settings needs to be mentioned in CR and schema deprecation possibly provided

nicxvan’s picture

nicxvan’s picture

nicxvan’s picture

Pushed this a bit further.

I removed the new config added the old back with the deprecation.

I added the new settings.

I need to remove the update hook and replace it with the correct post update hook.

nicxvan’s picture

Issue summary: View changes
nicxvan’s picture

Status: Needs work » Reviewed & tested by the community
Issue tags: -entity storage, -Needs issue summary update, -Needs upgrade path tests

I updated the Issue summary and Change record.

I finished converting this to follow the pattern from the translation path issue.

I'll keep an eye on tests, but this should be ready.

nicxvan’s picture

Status: Reviewed & tested by the community » Needs review

Meant to set needs review!

nicxvan’s picture

Assigned: claudiu.cristea » Unassigned
claudiu.cristea’s picture

Status: Needs review » Needs work

Did a review, see the MR

nicxvan’s picture

Status: Needs work » Needs review
Issue tags: +Needs subsystem maintainer review

I have addressed all feedback but deprecating field_purge_field and field_purge_field_storage without replacement.

I asked @amateescu on slack and he has it on his list to review.

Tagging for subsystem maintainer review.

claudiu.cristea’s picture

Thank you, @nicxvan. There's still one thing left related to the visibility of FieldPurger::purgeFieldDefinition() and FieldPurger::purgeFieldStorageDefinition(). Let's wait for a 3rd opinion

nicxvan’s picture

Yes, sorry that is what I meant, if we change the visibility then we need to deprecate without replacement.

I now agree with you we should, but it's really a decision for the field maintainer so I'll hold off for now.

amateescu’s picture

Status: Needs review » Needs work
Issue tags: -Needs subsystem maintainer review

Reviewed the MR.

nicxvan’s picture

Status: Needs work » Needs review

I made them protected, updated the deprecations and addressed all feedback.

claudiu.cristea’s picture

Ready to RTBC this but I've just noticed we need to update the CR https://www.drupal.org/node/3494023 because of the methods made protected.

claudiu.cristea’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: -Needs change record updates

Thank you. CR is reflecting now the changes. I cannot see anything else, this is ready.

larowlan’s picture

Status: Reviewed & tested by the community » Needs review

Reviewed this and left a couple of minor questions/nits

This is really close - would be good to resolve if

Note quite happy with putting more stuff in system cron.

was meant to be

Not quite happy with putting more stuff in system cron.

Because a one letter typo gives it a whole different meaning :)

nicxvan’s picture

I addressed all of your feedback thanks!

I didn't change the logger channel for the reason that @berdir stated.

I did see that potential typo, I only didn't reach out for clarification because this:

We could make it a separate cron hook, but ultimate_cron doesn't really support that yet right now due to invoke() only supporting a single hook for the given module

nicxvan’s picture

Status: Needs review » Reviewed & tested by the community

@larowlan said I could self rtbc, one is addressed the feedback.

alexpott’s picture

Status: Reviewed & tested by the community » Needs work

Nice work everyone - great to see this finally nearly done. Can we get a follow-up to remove the field.settings config object from Drupal 13.

One thing we need to address... we remove the config from config/install but we leave it lying around empty in the post update. See comment on MR.

nicxvan’s picture

nicxvan’s picture

Status: Needs work » Reviewed & tested by the community

The suggestion was applied and looks correct. I've created the follow up and @alexpott confirmed we do not need a todo anywhere so I think all feedback has been addressed.

alexpott’s picture

Status: Reviewed & tested by the community » Needs work

Just noticed another thing in the update... sorry.

claudiu.cristea’s picture

Status: Needs work » Reviewed & tested by the community

I've applied the suggestion.

alexpott’s picture

Version: main » 11.x-dev
Status: Reviewed & tested by the community » Fixed

Committed and pushed 867318c3996 to main and bfd87c3dda1 to 11.x. Thanks!

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

  • alexpott committed bfd87c3d on 11.x
    task: #2907780 Add a field purger service
    
    By: amateescu
    By: plach
    By:...

  • alexpott committed 867318c3 on main
    task: #2907780 Add a field purger service
    
    By: amateescu
    By: plach
    By:...

Status: Fixed » Closed (fixed)

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

pingwin4eg’s picture

The config name and its key were misnamed in the commit and the change record. The config name field.settings became field.field_settings, and its key purge_batch_size - field_purge_batch_size for some reason.

I opened a follow-up issue - #3622469: Fix field.settings:purge_batch_size config name and key and updated the CR.

Also, shouldn't the new setting be documented in default.settings.php?