Skip to content
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

Issue 157 follow refs #164

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open

Issue 157 follow refs #164

wants to merge 1 commit into from

Conversation

jbornemann
Copy link
Member

@jbornemann jbornemann commented Dec 29, 2016

Hey guys @viveksachdeva @sagarsane this should be good for a look over, with one minor outstanding question. It's a lot, so bear with me :-)

In general, what this PR means is that we can now have nodes write proper references.

If a node has weak (WEAK_REFERENCE) or strong reference (REFERENCE) properties on it, Grabbit will know to find referenced nodes, have them synched with the original node, and translate their original server jcr:uuid, to their new jcr:uuids on the receiving server. Protected reference properties that are not handled, do not have their reference nodes synched; just like they do not have their properties synched (e.g mix:versionable. Version storage nodes are not synched). Part of how we do this translation, is sending an identifier field along with mix:referenceable node messages. This identifier is only sent with referenceables, as it doesn't make sense for other node types - references can only reference mix:referenceables. The functionality also supports the case where weak references may have pointers to nodes which no longer exist, i.e groups with pointers to deleted users.

If an authorizable:

1.) Groups with members (ie. protected property 'rep:members', type WEAK_REFERENCE) will have their members synched as described above.

2.) If an existing authorizable is updated, it retains membership in other groups. In other words, when we update an authorizable, the node is recreated, and the jcr:uuid can potentially change. We don't want this to affect groups that have pointers to the original authorizable.

Framework for functionality demonstration, and testing:

1.) General node reference preservation. Create a node 'a' that has a weak reference to another node 'b'. Have a strong reference on 'b' that references a new node 'c'. Synching just 'a' should result in these references being preserved, and 'a', 'b', and 'c' being synched automatically. Order of events should not matter. Having a job path for 'a', 'b', and 'c' independently should not affect 'a's ability to point to 'b', or 'b' to 'c'. Verify this.

2.) Group membership. Create a new group 'test-group' in User Administration, and a few members 'user-a', 'user-b'. Add these members to 'test-group'. Synching 'test-group' should result in 'user-a', and 'user-b' being synched as well. Syncing 'test-group' independently of 'user-a', and 'user-b' should not affect this result due to test number 3 below.

3.) Group retention. After syncing updated 'user-a' alone, 'user-a' should still be a member of 'test-group'.

Other misc. changes:

  • Since groups automatically sync their membership, I added functionality to the proto authorizable node wrapper so that modifying the administrator is automatically avoided. This situation can no longer be fixed with configuration, as it was before.

Unsatisfied scenario with a few options :

Given a reference to a node whose parents are not yet synched on the receiving server, how should we proceed? If such as node's path was within a path configuration rather than reference, we would fail with VALIDATION_FAILED at configuration stage. We do this so that Jackrabbit does not write nt:unstructured intermediate nodes in place of actual parents. This is a easy scenario, because it is nice and deterministic feeling. Path within configuration are segregated, and easy to manage; and paths that we sync are known at configuration time.

This case is more difficult because a path configuration may contain a node which reference may point to a node synched as part of another path configuration. If parents are already synched, this is not a problem; but if they are not, it becomes a race condition.

Some options :

1.) Continue assuming segregation, and assume this is an unlikely corner case. No effort, no code, no expensive runtime checks. I feel unprotected reference properties on unstructured nodes are pretty rare in the wild. Any other option with the current fail-on-no-parent approach would require a runtime check on writing a given node - no one likes general performance degradation, especially for saving corner cases. If we hit 99% of cases, we are "good enough" for what it is. The downside to accepting, and acknowledging that particular scenarios are not handled well are that if our assumptions are wrong about what's common, or wild - this will come back to bite us.

2.) Keep 1 for now, but rethink, redevelop how we handle this missing parent scenario in general; especially with this in mind. We could always find a way to automatically sync bare minimum intermediate nodes, rather than fail. I think we mainly just fail now, rather than handle this automatically because at a certain point, it is better just to fix configuration than add code, and complexity to solve simple issues automatically; it's a non-trivial amount of code. With this, those days of thinking may be passing. These issues hopefully go away organically in this case. The downside is that if we are right about our assumptions above, we will have added unwarranted complexity to the project. Maybe not enough to panic though.

3.) Do a runtime check on node write, and fail the same as we would at configuration-time. This is simple effort wise, but it may result in a bad, confusing experience; and a bit more difficult to remedy than if it were a path configuration failure. Another down-side as mentioned above is performance. Reference nodes, vs your every day nt:unstructured nodes are written the same way - it's all generic, and should stay that way. This means we apply a penalty to all nodes, to save these cases.

I'm leaning on number 2. Thoughts? This is probably one of the longer PR descriptions I've written ;)

@review-ninja
Copy link

ReviewNinja

@jbornemann jbornemann self-assigned this Jan 3, 2017
@jbornemann jbornemann added this to the v8.0 milestone Jan 3, 2017
@jbornemann jbornemann force-pushed the issue-157-follow-refs branch 3 times, most recently from 2d314b6 to 9df5917 Compare January 6, 2017 05:41
@jbornemann
Copy link
Member Author

Would love some feedback on this when ever you guys get the chance :-) I was going to cut a 7.1 release with the user/group features after this guy.

/**
* @return true if the node at the path being written is being written to an existing node
*/
static boolean writingToExistingNode(@Nonnull final String pathBeingWritten, @Nonnull final Session session) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think method name is not making the intent clear... To me it seems that this method would write data to node, which it is not doing

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had a tough time coming up with a good name for this one. Suggestions?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am also having tough time thinking about a name for this.. :P writesToExistingNode or what you currently have should be fine.. 👍

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@jbornemann
Copy link
Member Author

Any additional thoughts on this? Was going to get it integrated? @sagarsane

@sagarsane
Copy link
Contributor

@jbornemann will be able to go through this hopefully after this week (release).

Btw, did you guys see https://blogs.adobe.com/contentmanagement/2017/03/20/aem-rockstar-tips-tricks-blog-series/ ? :)

@jbornemann
Copy link
Member Author

I did! So awesome! Congrats on being mentioned!!!

@sagarsane
Copy link
Contributor

Congrats to the whole team here :)

Automatically avoid modifying admin user

Extract parent existence logic into JCRUtil

Clarification in log message within ACL decorator
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants