-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
NC keys: When copying page nested content does not update properly #5913
Comments
@deMD I'm not sure I follow. Would you expect the elements on the copy to update automatically when you update elements on the original? |
Oops did not mean to close the issue, sorry! |
Update on this issue, just to make it even stranger. This problem seems to only occur when fetching multiple items:
When getting just a single item And when debugging, if I first resolve the third item in my watch window, I get that image in all copies + original I made a video where you can see what happens: https://youtu.be/_duHGDfH8o0 |
The problem is that the copied items have the same key. When you access the Image property, the value is cached with a key based on the element's key and the property alias, so each of the pages ends up looking at the same cache key. Whichever page you access first will populate the cache, then you'll get that cached value back for all other pages. The cache is per-request, so it's fine if you only fetch a single item per request. |
Yeah seems like that is the cause. Pretty nasty though that that happens for elements in nested content. |
This probably needs a fix in the caching layer, as making the keys unique (on copy) would require support for every property editor that uses As the example shows and @stevemegson explains, this bug will only surface when nested elements are fetched (and converted to an object/instance) from copied content within the same request. |
I can reproduce this as well. I'll have a look into it. |
PR in #5961 |
Is the PR for this fix still in view to be reviewed? |
We also like to get any update on this issue, since we also still struggling with it. |
I don't think we ever reached a conclusion on how this should be fixed. I believe the suggestions were:
Thinking about it again now, |
IMHO option 3 is the only real fix. Combining 2 GUIDs into 1 (by XORing the bytes) might still result in duplicate IDs, make debugging harder and introduce other bugs/unexpected outcomes (see #5961 (comment)). Passing/setting a cache prefix would probably be the easiest change, although that would probably be a breaking one and should preferably be done before 8.2.0 is released! |
Why would XORing two GUIDs make duplicate IDs more likely? The point about sites relying on the key to identify a nested element is a fair one, but in that case they may already be broken by duplicate keys. If we have a choice between always exposing the key that's in the JSON or exposing some other GUID which avoids collisions, I'm not sure which is better. I agree that option 3 is the best fix in theory, but I'm not sure what it looks like in practice. |
More info on this same issue: That makes the bug more frequent than the "duplicate" case. |
@JoseMarcenaro If the NC property is part of a composition that is added to a Document Type, the data is stored on the content node of that Document Type (not the composition and therefore not shared between other nodes), so I'm not sure how that would result in duplicate element keys... When using Content Templates however, you can add default NC elements that have the same key when new nodes are created using the template. This is basically the same as copying an existing node, but another way to have duplicate keys nonetheless. |
@ronaldbarendse - thanks for your thoughts. |
@ronaldbarendse - after some tests, I conclude you are totally right. |
While we decide on a permanent solution, this is a possible workaround. It replaces the standard property value converters for nested content with versions which disable caching. That will obviously have a performance impact if you're making heavy use of nested content, but I think it'll be acceptable as a temporary solution in most cases. |
Hi all, there's a lot of information both here and in the original issue #5961. For now, I'll keep the conversation here. IMO the GUIDs for each element should be unique since that is what we would expect it to be. They should be both unique and not change per element, for example, if one day we can persist elements to the DB, they will have their own unique GUID that won't change. Even though we are currently storing this data in JSON, it should be the same principal. I'm not a fan of having new random keys or non-consistent keys per request. Each of the stored keys should just be unique and consistent. To solve this issue a custom event handler for I do understand there's a complexity here. Currently nested content is the only editor that has unique keys per element that we'd need to take into account but the challenge is that nested content can be nested within other complex editors. Originally i was thinking of just being pragmatic and creating a It might be possible to detect nested content json within a json structure, and check if there's a GUID stored for any What do you think? |
@Shazwazza sounds like the most pragmatic approach for the time being. It might have a slight performance hit for bulk copy operations though. Also it needs to be able to handle Nested Content within Nested Content, as this is a quite common usecase. Also this has to be handled client side as well, since we can copy elements between content using the clipboard service. I believe Niels L already did some work towards achieving this. On the server side, a different approach could be to introduce a "you're being copied" event system on property level and let Nested Content and the like do their own thing. This would probably scale better for 3rd party editors. But it would probably also end up being a breaking change. |
I agree with @enkelmedia would be great for Core to prioritise this fix in-house especially since @Shazwazza has a great handle on what needs to be done. I've noticed the same issue when trying to copy nested content on one of my projects. Happy to offer my own Angular JS skills to help out. btw, you guys at HQ are doing a great job! |
What has been done so far? It's along thread.
If they have been fixed, I will make a patch for all of our clients to fix all duplicates. |
@madsoulswe I think the ClipboardService has been fixed in #7166. And I believe #8177 also resolves duplicate key issues when copying nodes that contain nested content. Both PR's were included in the 8.6.2 release. However, this still leaves us with duplicate keys that were saved before these fixes were applied. If you come up with an idea to reset the nested content keys for all existing content, please let me know. I'm not concerned about Deploy/uSync/etc. scenarios. I wonder if it's even possible to reset keys when these scenarios are involved. |
I’ve found a way to replace all existing keys in the umbracoPropertyData table for all nested content data types and only for current content versions, using the logic that was included in #8177. But these changes are only reflected after each node is republished. Where does Umbraco fetch its property data from when loading a page? Is it the cmsContentNu table? Is there an easy way to rebuild the cache after manually updating values in the umbracoPropertyData table without having to republish the affected nodes. |
@creativesuspects Can you share the code you used to update the keys? You can rebuild the |
@creativesuspects It's getting it from (predictably) I don't think there's a great way to fix the keys at the moment, other than going through each row in |
@nul800sebastiaan That's exactly what I did: Fetch all records from umbracoPropertyData that contain nested content data types for current content version. And then loop through each record and replace the keys:
The logic for However, the cmsContentNu table still contains the old property collection for each affected page. And regenerating the NuCache doesn't seem to do anything. I've also tried clearing out /App_Data/TEMP/ followed by an application pool recycle and what not. For some reason the new property data only becomes visible when republishing the affected page. Am I missing something? Edit: It was late last night / this morning. So I'm going to retrace my steps later today to double check that rebuilding database and memory cache actually doesn't work in this case. |
After rebuilding NuCache (from the dashboard in the developer section), you still need to read the new cache into memory, I could only make that happen with an app pool recycle. Your mistake is that you're using |
This is the SQL that gives you all of the results for all versions:
|
Yep, as long as each key is unique it's fine. I will give that a try and let you know what happens. |
@nul800sebastiaan @rbottema Okay, so that seems to work. Also, I just realized I had previously been reloading Memory Cache before reloading the Database Cache, so that might have been an issue as well. Like I said, it was very late. I have only tested it on a very small site with only a few content nodes, but I'm going to do some more testing on a larger site with multiple language variants to make sure it works. So to sum it all up, here's what I did:
|
Duh me too, the right way around works indeed 👍 |
@nul800sebastiaan So are you sure we couldn't include the |
It's not going to perform well in any case on large sites, but with a lot of version it will be pretty slow. I am not sure how to know which version is actually published, but Aha, hang on you can use this one instead: SELECT id, textValue FROM umbracoPropertyData WHERE versionId IN (
SELECT id FROM umbracoDocumentVersion WHERE published = 1
)
AND propertyTypeId IN (
SELECT id FROM cmsPropertyType WHERE dataTypeId IN (
SELECT nodeId FROM umbracoDataType WHERE propertyEditorAlias = 'Umbraco.NestedContent'
)
)
Ah but you'll still need to update |
This seems to do the trick for both: SELECT id, textValue FROM umbracoPropertyData WHERE (versionId IN (
SELECT id FROM umbracoDocumentVersion WHERE published = 1
) OR versionId IN (
SELECT id FROM umbracoContentVersion WHERE [current] = 1
))
AND propertyTypeId IN (
SELECT id FROM cmsPropertyType WHERE dataTypeId IN (
SELECT nodeId FROM umbracoDataType WHERE propertyEditorAlias = 'Umbraco.NestedContent'
)
) |
On second thought it's probably best to just replace ALL records in case someone decides to do a rollback on a page, because that would also bring back those duplicate keys. |
That's true! |
Again, I haven't tested this fix on a large(r) site. But do you have any idea if it could be applied to a site with hundreds or thousands of content nodes, or would that just take forever? |
You can let me know! ;-) |
Just tested it on a relatively new site which heavily depends on nested content with a few hundred content nodes and two language variants: 3398 records updated in 21.430 seconds. It's still not a huge site, but the fix executed fairly quickly. Of course when you have a lot more content nodes and a lot more versions per content node running the fix may eventually become a problem. Note 1: I've been testing on a remote SQL server instance, so there's probably some network latency involved as well. Note 2: I've just tested it on a couple of production sites (SQL server instance and IIS are on the same server): 3392 records updated in 3.444 seconds |
So this issue has been open for almost a year and still no solution? :( If the copy-paste function does not work properly, then why not disable it? Editors will be very confused with this experience? Please do not tamper with the Guids for the nested block elements - we really need them on our project as a reference! |
@kimschurmann As of v8.6.2 this works now, with one caveat, something went wrong with the release and there's a manual fix for that available at the moment: #8223 - that will be fixed in 8.6.3. I will close this issue now as a "duplicate" of #7133 which was marked as fixed and released in 8.6.2. |
This issue description has been updated with a propsed solution and has been marked as up for grabs. Please read below about the original issue and the proposed solution. You can also scroll way down to read the entire discussion and history.
Proposed solution
Taking some inspiration from the media tracking branch and looking at what we already have in core:
IDataValueEditor.FromEditor
to re-populate any missing keys. Nested content already overrides this method so it would be just adding the logic to check for empty keys. Empty keys may be sent up if the client side clears them when copying them with the clipboard service. Nested content calls FromEditor recursively so if there's an NC inside an NC this will still work.IDataValueCopying
which can be implemented by anyIDataValueEditor
(like likeIDataValueReference
for media tracking). It could have one method like:object Copy(object input);
ContentService.Copying
, the event handler will use the currentIContent
along with thePropertyEditorCollection
to figure out if any of theIDataValueEditor
s being used for any of the properties implementIDataValueCopying
and if so, will invoke theCopy
method and set the new property value to the result.NestedContentPropertyValueEditor
then implements this interface and it will have to deal with having nested nested contents but that shouldn't be too difficult.Original submitted issue
When we copy pages with Nested Content and edit a published element the copied page still shows values from the original content. For example an image block where we changed the image still gives us the original image when checking the strongly typed model. The source value of the property does update properly, as demonstrated in the image below:
Reproduction
This bug appears in Umbraco version 8.0.2
This item has been added to our backlog AB#6684
The text was updated successfully, but these errors were encountered: