Problem/Motivation
Discovered in #3003586-21: [PP-4] Use setStorageRequired() instead of overriding the storage schema to mark fields as NOT NULL in the database where the update test fails. The problem is that the only returned revision metadata key in
/**
* Move revision metadata fields to the revision table.
*/
function system_update_8400(&$sandbox) {
for the block content entity type is workspace when retrieving the keys with $revision_metadata_fields = $entity_type->getRevisionMetadataKeys();. The problem is that the BC layer runs only when the property is not initalized or matches the required revision metadata keys property. However a Workspaces update 8801 updates only the one property inbworkspaces_update_8801().
Potentially there might be a similar problem in workspaces_module_preinstall().
Proposed resolution
In the update modify both properties on the installed entity type similar to the system update 8501 - revision_metadata_keys and requiredRevisionMetadataKeys.
Updating both properties will allow the BC layer to run property.
Remaining tasks
User interface changes
API changes
Data model changes
Release notes snippet
| Comment | File | Size | Author |
|---|---|---|---|
| #80 | 3098427-80-8.9.x-and-8.8.x.patch | 2.36 KB | amateescu |
| #80 | 3098427-80-9.0.x.patch | 1.22 KB | amateescu |
| #78 | 3098427-78.patch | 1.14 KB | amateescu |
| #73 | interdiff-73.txt | 487 bytes | amateescu |
| #73 | 3098427-73.patch | 23.12 KB | amateescu |
Comments
Comment #2
hchonovComment #3
hchonovThis is only test to show what happens when a workspace update gets a dependency on a system update. As they are completely independent nothing should go wrong, but it does and it is exactly regarding the revision metadata keys.
Comment #4
hchonovThis now rewrites the workspaces update to add the workspace revision metadata keys as we've done in
system_update_8501().And there is a fix only patch.
Comment #5
hchonovComment #7
amateescu commentedThe
requiredRevisionMetadataKeysproperty was added in #2936511: ContentEntityType::getRevisionMetadataKeys() never considers the BC logic because of the new "revision_default" key for non-optional fields provided by the Entity API (likerevision_default), but the newworkspacerevision metadata key is very much optional.Comment #8
plachComment #9
hchonovThis is how new keys should be added. Otherwise the BC layer is broken.
Requiredhas a different meaning here. The key might still be optional. We've documented the property like this:However it can be filled also from outside.
------
The current patch also fixes the problem in
workspaces_module_preinstall().Comment #10
hchonovOh we need to update
\Drupal\workspaces\EntityTypeInfo::entityTypeBuild()as well.Comment #11
xjmSilly me, thinking I could search for 8.8.x issues to monitor 8.8.0. :)
Comment #13
hchonovJust an oversight ...
Comment #14
hchonovMaybe like this, which we are doing also in
\Drupal\Core\Entity\EntityFieldManager::buildBaseFieldDefinitions()for therevision_defaultrevision metadata key.Comment #15
catchBumping to critical.
Comment #16
daffie commented@hchonov: Can you explain why your solution will work and can you add testing.
Comment #17
hchonovMy solution works because if we update only one of the two properties -
revision_metadata_keysorrequiredRevisionMetadataKeysthen the BC layer will not be triggered and revision metadata keys not declared in the entity type annotation will not be found. The condition for the BC layer in\Drupal\Core\Entity\ContentEntityType::getRevisionMetadataKeys()is :if ((!$this->revision_metadata_keys || ($this->revision_metadata_keys == $this->requiredRevisionMetadataKeys)) && $include_backwards_compatibility_field_names)Adding a key to
revision_metadata_keyswill lead to the first condition evaluating to FALSE, which is why, we've introduced a second property -requiredRevisionMetadataKeys. So if we update both properties and they are equal, then the BC layer will still be executed. However this will not happen if we update only therevision_metadata_keysproperty.I've added the test showing this behaviour.
Comment #18
daffie commentedShort review and I have 2 points:
We can remove this part of the test. It is double.
Comment #19
hchonovNo, it isn't double. There are 2 different cases being tested.
I've added two test cases, the first one shows what happens when the BC layer is not triggered. It is not supposed to fail. A failing patch, that will be solved by my solution can be only an artificial one that rearranges the updates, but this is not something we are going to do here. I've demonstrated what happens when the updates are rearranged in #3
Comment #20
daffie commentedComment #21
hchonov@daffie, this test show that the BC layer is not triggered. It will fail only if the BC layer gets triggered, which does not happen and therefore there are only 2 keys returned.
Comment #22
hchonovRe-uploading patch from #17.
Comment #23
daffie commentedThe fix in this patch looks good to me.
The added tests look good too. Only they do not test the proposed fix.
The patch with only the added tests passes without the fix.
I have chatted with @hchonov and he states that:
I leave it to the committer if this is acceptable (possibly remove the added tests).
Comment #24
amateescu commentedI'd like to take a look at this.
Comment #25
amateescu commentedThere are two things to discuss here:
1) If a fix is needed for the upgrade path tests, then the patch attached which switches that test to a newer db fixture should be enough.
The current update tests from the Workspaces module cover a situation that can not exist: a fixture of Drupal 8.0.0 with the Workspaces module installed, when the module was only added in 8.6.0.
The only theoretical update failure scenario would be if a site updates directly from 8.3.x to 8.8.x, but, in that case, the Workspaces module couldn't have been installed.
2) If a fix is needed to cover the current issue title ("Manipulating the revision metadata keys before running the BC layer breaks the BC layer"), then I don't think #22 is good for the following reasons:
#9 says
This is not documented *anywhere* (the doxygen block for
$requiredRevisionMetadataKeysonly says something about new vs. cached instances of the entity type class), and it's a terrible DX if it's truly the only way to add a revision metadata key.The current solution for providing the BC layer of revision metadata keys (using
$requiredRevisionMetadataKeys) was committed in #2936511: ContentEntityType::getRevisionMetadataKeys() never considers the BC logic because of the new "revision_default" key and it is largely based on comment #18 from that issue:This doesn't take into account the possibility of other core/contrib/custom modules providing revision metadata keys for entity types that they don't own/control (i.e. what Workspaces does in 8.8.0), and forces them to code specifically for the BC layer.
Comment #26
hchonovI don't have time to answer everything right now, but this quickly:
We just have never considered allowing additional revision metadata keys beside the ones defined by core. Therefore I will not call a non existent feature terrible DX. What workspaces has already done was to "hack" core to make that possible, which is why it was updating the property directly instead through a dedicated API and this isn't documented as supported anywhere.
It is the BC layer making it that complicated. When it is removed everything will become much easier.
Comment #27
amateescu commentedYes, that's the conclusion of #25 as well, see the last paragraph.
What do you mean by "hacking" core? There is no dedicated API for adding a revision metadata key to an entity type definition, like there is no dedicated API for adding a regular entity key, it's all done through the generic
\Drupal\Core\Entity\EntityType::set()method and it has been like that since 8.0.0.Comment #28
amateescu commentedComment #29
hchonovWe both agreed that core does not support extending the revision metadata keys. Doing it any way is kind of "hacking" core. This is what I've meant. It might be okay to add entity keys through the set method, but not revision metadata keys without considering the BC layer. I don't like it either, but luckily it will be removed soon.
Being not documented is not a reason not do it given all my explanations how it behaves and how we already did use it in a system update. See #4.
Are there any objections regarding #22 beside not being a documented approach? Please note that the way workspaces is currently adding revision metadata keys is not only not documented, but also completely unsupported at the moment. But still I am not going to argue that all that code should be removed from workspaces. In fact I think it can stay if we do #22 to consider the BC layer properly. If it is not a suitable solution for workspaces to have to deal around the BC layer this way it can just add a revisionable non-translatable field instead of a revision metadata key, however I don't think that anyone would be in favour of such a solution.
Yes, unfortunately it is so. However I don't think that it is worth it adding a way to support this for a BC layer that is being removed in Drupal 9.0.0. However this is still not a reason not to do #22.
Comment #30
amateescu commentedI'd be ok with #22 only if we add a
ContentEntityType::setRevisionMetadataKey()method, because Workspaces (or any other module) should not have to know or code around the internal implementation of a BC layer.But, as explained in #25, that patch should be enough because a site needs to be on Drupal 8.6.0 in order to be able to install Workspaces, and at that point the BC layer has done its job already.
Comment #31
hchonovThat's true, however only if doing something officially supported. As it is already clear that we haven't thought of allowing others to hook in and provide revision metadata keys I don't think that it is fine to introduce this method and functionality as part of fixing the current critical bug fix given the fact it is doable and already done in #22 without this overhead. We could discuss such a feature in a "feature" but not in a "bug" issue.
Only for the installed definitions, not for the live ones. Their BC layer will still be broken.
Comment #32
amateescu commentedWe can mark the new helper method as
@internalfor now, which keeps it "unsupported" as far as core's public API policy is concerned.Comment #33
alexpott@hchonov asked me to think about whether #22 or #25 plus a new helper is the right way to go.
I'm inclined to agree with @hchonov that a new helper method (even marked @internal) to support a BC layer that's not going to be in Drupal 9 feels unnecessary.
But also if the changes to
\Drupal\workspaces\EntityTypeInfo::entityTypeBuild()are necessary to fix the live definitions and the live definitions are currently wrong on 8.8.x then we should test this.So I guess what I'm saying is that I think we should merge #22 and #25 to fix the update test so that it is updating from a more real point and fix the live definitions and the live workspace definition should tested top prove that we've fixed it.
Also I'm not sure that this is critical bug anymore. Like is there a situation where the update can fail?
Comment #34
amateescu commentedThe new helper method would not be added specifically for the BC layer, it will be helpful even in 9.x and beyond for code that wants to add a revision metadata key to an entity type definition. It's just that in this case, it will help with not spilling the internal implementation of that BC layer to other places that have nothing to do with it.
I guess the proposal was not clear enough, so here's a pseudo-implementation of this helper:
8.8.x and 8.9.x:
9.x and beyond:
\Drupal\Core\Entity\EntityTypehas many helper setters like this:setHandlerClass(),setStorageClass(),setFormClass(),setListBuilderClass(),setViewBuilderClass(), etc., so it's not like we would do something novel here..Comment #35
hchonovAddressed all the points from #33, merged the test coverage, added dedicated test coverage. The new test is flagged as legacy just because of the deprecation messages, but we can just remove them and it still will remain a valid test for 9.x.
No, the updates will not fail, but an entity type might still be installed with the wrongly estimated revision metadata keys. This will be the case for new entity types installed after workspaces, but not defining the revision metadata keys yet. As a consequence the revision metadata fields will be placed in the wrong tables.
Comment #36
alexpott#34 is quite compelling - how about we file a follow-up for that? At the moment the only other use case in core is system_update_8501() which we're about to delete and this code. So I think we'd need to envisage further usages or be able to point to contrib that's getting it current wrong to help provide a basis for adding the new API.
AS this update is already in 8.8.0 I think this needs to be in a separate update no?
Is the filled-ness important?
Comment #37
hchonovMakes sense even though it is an experimental module => Done.
We are filling some node entries so this should be enough if that is important.
Comment #39
amateescu commentedThe new test doesn't fail because its namespace declaration is wrong. Here's the minimal test-only patch.
WorkspaceRevisionMetadataFieldTestfails because thedrupal-8.2.0.bare.standard_with_entity_test_revlog_enabled.php.gzdb fixture doesn't contain the installed definition for the newentity_test_mul_revlog_pubentity type.@alexpott, re #36: we already have an additional use case in contrib, in the Revision Tree module, and another one coming up in the Trash module.
This means there are at least 7 places (3 in core - this patch, 4 in contrib) where we have to repeat BC-aware code, which in turn means that those contrib modules can not have a release that's compatible with both Drupal 8.x and 9.x at the same time (the whole point of having BC layers), so I really think that we need to add the helper setter method in this issue.
Comment #40
hchonovDidn't the move fields tests fail for that reason? If I am not missing something it will still fail.
We can't make the current issue ready with the current scope yet. I am fine with having a dedicated method, but it is out of scope here and will unnecessary delay the current issue.
We can totally work in parallel on the method in a different issue.
Comment #41
amateescu commentedYes, the move tests still fail. I didn't update the fixture to include the new entity type, I just pointed out why it fails.
The full patch from #39 wasn't generated with
--binary, so here's a better one. Leaving at NW because the fixture needs to be updated.@alexpott, what do you think about #39, should we do it here or in a new issue?
Comment #42
hchonovThe fixture is for 8.2 and the EntityPublishedInterface has been introduced in 8.3, so it is not possible to include the entity type without completely updating the fixture to 8.3.
Can we add an update for installing the entity type in the test module instead of updating the fixture where it is contained?
Or maybe create a new test module?
Comment #43
alexpott@amateescu you've convinced me...
Let's do this here. It's a minimal thing and does make things easier for everyone. The fact we have all these other use-cases is the reason I've changed my mind.
Comment #44
amateescu commentedThanks, @alexpott :)
Updated the patch to add the helper method, fixed the failing tests by installing the new entity type in an update function and moved the workspace_association cleanup to
workspaces_update_8803(), which was just introduced by #3099986: Move part of workspaces_post_update_move_association_data() to a hook_update_N and hasn't been part of a published release yet.Comment #45
daffie commentedPatch does not apply.
Comment #46
meenakshig commentedComment #47
daffie commented@Meenakshi.g: Could you also post an interdiff.txt file. Such a file makes it easier for reviewers to see what you have changed in your new patch file. See: https://www.drupal.org/documentation/git/interdiff.
Comment #48
meenakshig commented@daffie patch was not working because it cannot apply the binary patch to without full index line so there is no difference in interdiff
Comment #49
amateescu commentedOops, I forgot that this patch needs to be diffed with
--binary:/ This patch is #41 with the interdiff from #44 and rolled properly.Comment #53
amateescu commentedFixed those fails.
Comment #54
amateescu commentedI think that all the reviews and open questions have been addressed, so the patch looks ready for another round of committer feedback.
Comment #55
daffie commentedTestbot failure.
Comment #56
amateescu commentedTestbot is back to green now.
Comment #57
xjmComment #58
alexpottSo the documentation in ContentEntityType directly contradicts what is going on here. It says:
So we need to update that documentation as to why this is okay.
Also all the revision metadata key logic could do with a unit test as we're about to remove update paths in 8.9.x and 9.0.x so we might endup with stuff being completely untested.
Comment #59
amateescu commentedThanks for taking another look @alexpott :)
Regarding the first point from #58, I think the documentation for that class property is bogus because #9 says that it can (and should) be filled from the outside when adding a new revision metadata key. Also, given that it's basically repeating a small part of the inline documentation from the constructor, let's remove it.
Regarding the unit test, keep in mind that this BC layer also goes away in 9.0.x (#3099789: Remove the BC layer for revision metadata keys), so, in that issue, the new method added here will become a simple setter, which shouldn't require any special testing IMO:
Comment #60
alexpottDoes
system_modules_uninstalled()need to remove the required key too?And what about
\Drupal\workspaces\EventSubscriber\EntitySchemaSubscriber::onEntityTypeUpdate()and\Drupal\workspaces\EventSubscriber\EntitySchemaSubscriber::addRevisionMetadataField()do they need to deal with the required metadata key?Comment #61
amateescu commentedGreat point! This should do it.
Comment #63
amateescu commentedFixed those fails and added test coverage for the problem that @alexpott discovered in #60.
Comment #64
berdirThis doesn't apply to 9.0.x anymore now, I'm not quite sure what we need to do now exactly as the upgrade path there has been removed, do we still need to commit some of this there? I suppose so...
Comment #65
jibranNW for #64.
Comment #66
jibranWe have to change this to
8.8.0and then changedrupal-8.6.0-workspaces_installed.phptodrupal-8.8.0-workspaces_installed.phpas well which we added in #3087644-50: Remove Drupal 8 updates up to and including 88**Comment #67
catchI don't think it's necessary to update the test coverage as such, we can probably just do separate 9.0.x and 8.9.x patches:
9.0.x with the runtime changes and entity_test_revlog + associated test coverage.
8.9.x also including the workspaces update test.
Comment #68
berdirI was thinking the same, maybe we could just directly use #3099789: Remove the BC layer for revision metadata keys for the 9.0.x issue, as that was then already removing a good chunk of this again I believe.
Comment #69
damienmckennaTagging as a requirement for Drupal 9.0-beta1.
Comment #70
berdirSetting this back to RTBC, as my understanding is that this is now only for D8 and #3099789: Remove the BC layer for revision metadata keys is the standalone companion issue for D9. Might want to wait until the D9 issue is also ready so we can commit them together though?
Comment #72
catchRandom fail...
Would be good to commit this and #3099789: Remove the BC layer for revision metadata keys close to each other yes.
Comment #73
amateescu commentedI looked at the patch again and noticed that we were missing a
returnstatement for the newsetRevisionMetadataKey()method. Fixed that quickly.Comment #74
alexpottAs we're changing updates that have already been released don't we need to add an 8804 update to do this?
Comment #77
catchThat's an unfortunate crosspost.
I read back through the issue history:
@alexpott asked for a new update in #3098427-36: Manipulating the revision metadata keys before running the BC layer breaks the BC layer
@hchonov split it out in #3098427-37: Manipulating the revision metadata keys before running the BC layer breaks the BC layer
In #3098427-44: Manipulating the revision metadata keys before running the BC layer breaks the BC layer @amateescu correctly pointed out that the original update hadn't been in a tagged release yet, so moved it back inline.
However two months has passed, and there's now been a tagged release.
So... I think we need to add the hook_post_update_NAME() back, and commit that to 9.x, 8.9.x, and 8.8.x - the post update can stay in 9.x for workspaces users that already updated to Drupal 8.8.2.
Since this requires a 9.0.x commit, seems simplest to do it in a follow-up patch but remaining on this issue.
Really this was an unrelated problem with the workspaces update that we could have split out to a follow-up, although did not really hurt to include it here given it's touching the same code, except for update path/tagged release race condition.
Comment #78
amateescu commentedWhoa, that's really unfortunate indeed. Let's do a quick followup patch here to fix 8.9.x and 8.8.x, and I'll open another issue to move this code to a post-update for 9.0.x as well.
Comment #79
catchThe post update is missing from #78.
I think we can commit the 9.0.x patch here too.
Comment #80
amateescu commentedOkay, let's do everything here then :)
Comment #81
catchThanks patches look right.
Comment #82
alexpottCommitted c02ff06 and pushed to 9.0.x. Thanks!
Committed and pushed f94693e842 to 8.9.x and 6fa0f86b39 to 8.8.x. Thanks!
#78 proves we have test coverage.