Problem/Motivation
During config import for server entity, backend_config section isn't being imported properly because of call to \Drupal\search_api\Entity\Server::toArray method, which rewrites the newly incoming backend config with active config.
This breaks the code-driven development flow, and requires us to manually set the desired backend settings in form and save it.
I'm using version 1.5 of the module on project, but the behavior is the same with 1.8 and the code is still there in 1.x-dev
There is a //todo in the method added, which states that this is a bug.
Proposed resolution
Removal of the method solves the case with config import. But I have doubts that this wont cause any other issues where this ::toArray() method must be used with the override for the active configuration.
Remaining tasks
- Discover the purpose of the bug code introduced in ::toArray() method
- Find a way to allow proper config import of the server entity config
Comments
Comment #2
borisson_This was removed in #2242361: Coding standards clean up, then added again the commit after it, but that is all the information that I have about this.
Comment #3
drunken monkeyI can't reproduce this.
Can you provide steps for reproducing reliably?
Have you tried this with a vanilla installation of Drupal with just this module?
Comment #4
vflirt commentedI can confirm I have the same use case. I have debugged it down to the same issue - \Drupal\search_api\Entity\Server::toArray
So even in the config file the 'backend_config' is different this method will always load it from the active config. Even if other developer does changes to the 'backend_config' they will never get updated as they are always replaced from this function so code sharing and deployment is broken and not working and requires to do all the changes manually in order to get the config in sync.
A start point would be Drupal\Core\Config\Entity\ConfigEntityStorage::importUpdate method.
Comment #5
vflirt commentedComment #6
drunken monkeyInstead of re-iterating that you think this is broken, could you please give me steps to reproduce this, like I asked? Because I just tested again, and still can’t. It works fine for me.
Comment #7
vflirt commentedIt seems to be a bit more complicated after looking more into it. It is working ok on a vanilla install with just this module.
The way to break things:
1) implement hook_search_api_server_load
2) call $entity->getBackend() for each of the loaded entities, no need to do anything else
3) export current server config
4) edit the config file and change any settings
5) try to import the server config and observe it does not work
As described this is caused because the Config Import will call the toArray method, which would call the getBackend which checks for $this->backendPlugin , as this was already initialized in the hook_load and will use it instead of loading the one from the new configuration.
To me getBackend() method functions as it should so it does not reload. Is there any specific reason to load the backend config in the toArray() method? As written by @Spurlos "Discover the purpose of the bug code introduced in ::toArray() method" but no info has been provided why is this needed, maybe there is better approach here.
Comment #8
drunken monkeyThanks for providing this information! With this, I was finally able to reproduce the problem, and also easily write a test checking for it. (Great first step for any bug report.)
The info why this is needed is right in the
@todocomment: If someone callssetConfiguration()on the backend plugin, instead ofsetBackendConfig()on the server entity, we still want to preserve those changes. This is, for example, important when submitting the backend plugin’s form, as that just stores the changed config on the plugin.However, I see a lot of options for resolving this problem:
isSyncing()inServer::toArray()to avoid the call during config import.setConfiguration()implementation ofBackendPluginBaseto also propagate the change back to the server entity, eliminating the need for the code inServer::toArray(). (To avoid infinite loops, instead of using a$should_propagateargument, as the@todocomment suggests, it should be enough to check whether the two are actually different, and not do the call otherwise.)Problem with this is that, in theory, that method could be overridden. In practice, though, I think all overrides will/should call the parent method, so this shouldn’t actually be a problem.
$backend->setConfiguration()directly – i.e., do more or less the same as above, but also add a deprecation warning. In this case, we’ll also have to overridesubmitConfigurationForm(), though, which is rather tricky because it’s in a trait, not on the plugin base class. So, probably not the best option.Server::set()to callsetBackendConfig()if it is called with'backend_config'as the$property_name, which should eliminate the problem during import. (\Drupal\Core\Config\Entity\ConfigEntityBase::set()already has a very similar check for entities implementingEntityWithPluginCollectionInterface, but unfortunately this doesn’t look like an option for us (anymore), as we’d have to change the entity structure for that.Attached are patches implementing options 1, 2 and 4, all of which seem to be working fine. Please test/review!
Also, any opinions of which of these make the most sense would be appreciated.
Comment #11
drunken monkeyThe
hook_search_api_server_load()implementation caused an error in an unrelated test.Comment #13
sker101 commentedI started having this issue after updating acquia connector to `1.21` and I confirmed that the patch #11 fixed the issue.
Comment #14
drunken monkeyThere are three patches. Which one did you try – or did you try all of them?
Comment #15
sker101 commentedMy mistake, I only tried the last patch "2976339-11--server_config_import_issue--Server_set_override.patch" and it seems to work fine so far.
Comment #16
drunken monkeyThanks for reporting back!
As no-one else has weighed in on the code aspect, I reviewed again myself and decided that I like the second patch best. Would you mind giving that a try, too, to make sure it works as expected? Then I can commit and finally resolve this issue.
Comment #17
sker101 commentedI tried the second patch as you suggest on version 1.17 and confirmed that it's working on my end as well.
I also tried to remove the patch and then updated acquia connector to 1.22 (the latest release) to see if it has been fixed somehow on their end and was still seeing the issue.
Comment #19
drunken monkeyExcellent, thanks a lot for testing!
Committed. Let’s hope this fixes the issue.