Problem/Motivation

Due to the introduction of closures in the constructor parameters in #3452414: Refactor storage class generation and #3560348: Improve handling of the 'in_trash' query parameter.

The following exception is thrown when certain elements are being serialized:

Serialization of 'Closure' is not allowed

I think normally the entity type manager should not be serialized (and instead classes referencing it should use the DependencySerializationTrait in order to serialize it), but the Trash entity type manager decorator doesn't serialize the internal core entity manager leading to this issue.

Steps to reproduce

In my particular instance, it happens on a clean site install, and in particular when webform_views triggers a call to the ElementInfoManager::buildInfo() which then tries to serialize the break_lock_link pre-render array and add it to the MemoryBackend.

Example closures being referenced:

[
  0 => 'root[break_lock_link][#pre_render][0][0]->entityTypeManager->inner->handlers[views_data][block_content]->moduleHandler->alterHookListeners[entity_type][17][0]->trashManager->entityDefinitionUpdateManager (Closure)',
  1 => 'root[break_lock_link][#pre_render][0][0]->entityTypeManager->inner->handlers[views_data][block_content]->moduleHandler->alterHookListeners[entity_type][17][0]->trashManager->entityLastInstalledSchemaRepository (Closure)',
  2 => 'root[break_lock_link][#pre_render][0][0]->entityTypeManager->inner->handlers[views_data][block_content]->moduleHandler->alterHookListeners[entity_type][17][0]->trashManager->trashHandlers->generator (Closure)',
  3 => 'root[break_lock_link][#pre_render][0][0]->entityTypeManager->inner->handlers[views_data][block_content]->moduleHandler->alterHookListeners[entity_type][17][0]->trashManager->trashHandlers->count (Closure)',
  4 => 'root[break_lock_link][#pre_render][0][0]->entityTypeManager->inner->handlers[views_data][block_content]->moduleHandler->hookImplementationLists[modules_installed]->listeners[18][0]->configFactory->eventDispatcher->listeners[kernel.request][500][0][0] (Closure)',
];

Proposed resolution

Until core supports serialization of [#AutowireServiceClosure] (and maybe #[AutowireIterator] in #3544994: Make service closures serializable in classes using DependencySerializationTrait, we need to manually ensure that the known services using closures (and referencing the entity type manager) can be serialized and unserialized as they may be referenced in certain hooks.

Remaining tasks

Provide MR.

User interface changes

N/A

Issue fork trash-3588477

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

codebymikey created an issue. See original summary.

codebymikey’s picture

Title: The TrashEntityTypeManager can't be serialized » The TrashEntityTypeManager and certain services can't be serialized
Issue summary: View changes
Status: Active » Needs review

Ensure most of the services that may be potentially referenced as part of a pre-render hook are serializable.

edit: On further thought, given that core's EntityTypeManager wasn't serializable in the first place, I think the real issue might be because the TrashEntityTypeManager has public: false, so the ReverseContainer is unable to resolve and instantiate it properly.

Perhaps more thought might be necessary on the other services which also have the public: false property.

codebymikey’s picture

StatusFileSize
new12.3 KB

Attached a static patch addressing the serialization issues - it also works as part of a clean site install.

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

amateescu’s picture

It seems I went a bit overboard with cleanup and optimizations that are not properly supported by core yet :) However, instead of trying to make it work via custom __sleep/__wakeup implementations, I'd rather go back to using static instantiation when needed.

This looks ready to commit now, but I'll wait for a confirmation that my changes haven't introduced any new issues.

codebymikey’s picture

Status: Needs review » Needs work

Just did a quick clean site install against the current MR (applied on top of the #3376216: Translation support issue fork) and unfortunately the current version still resulted in a crash on one of the nested closures:

root[break_lock_link][#pre_render][0][0]->entityTypeManager->inner->handlers[route_provider][block_content_type][html]->entityFieldManager->typedDataManager->discovery->derivers[entity]->bundleInfoService->moduleHandler->alterHookListeners[menu_links_discovered][2][0]->configFactory->eventDispatcher->listeners[kernel.request][500][0][0] (Closure)

I think there might be something special happening during the install phase causing it to be unable to resolve the newly decorated service. Making the decorated entity manager public gets past the closure serialization issue.

You can test this by :
1. Adding trash to the standard profile's install list.
2. Running drush site-install standard -vvv --site-name=Trash test --db-url=sqlite://localhost/:memory: -y
3. It should result in the unable to serialize 'Closure' exception.

Not sure if it's worth trying to add a test case for a profile installation.

amateescu’s picture

Status: Needs work » Needs review

Looked into it and the problem is Drupal's ReverseContainer which doesn't look at private services like Symfony does.

Anyway, we need to make our decorator public at least until core steps up its game. Added a test as well because Trash is enabled by default on Drupal CMS, so it would good not to break it :)

amateescu’s picture

Title: The TrashEntityTypeManager and certain services can't be serialized » TrashEntityTypeManager and other services can't be serialized
amateescu’s picture

Status: Needs review » Fixed

Merged into 3.1.x, thanks for finding and sticking with this issue!

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.

Status: Fixed » Closed (fixed)

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