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
Use a userspace lastmodified property instead of jcr:lastModified #1033
Conversation
I don't understand all of this, but what I do understand, I like 👍 |
Most of the heavy lifting was from @escowles 👏 |
well congrats to both of you |
This is just an observation and is probably a question of timing and PR order, but I noticed that you guys have a couple I'm going to try this with my pcdm:Collections and see if the membershipResource gets reindexed when a new proxy is added. |
Soooo, maybe I'm missing something but was this supposed to resolve the issue of not emitting events when |
@whikloj This PR addresses a number of related issues. The first is that of ETags. The current Fedora release uses the JCR-based lastModified property, which changes every time something changes with a resource (good) and every time any other resource links to that resource (bad). As a byproduct of using a user-space last-modified property, we have more control over when the last-modified property changes -- including when a resource changes due to a change of LDP-based membership triples (i.e. direct and indirect container). And with this PR, when LDP membership triples change, the user-space last-modified property changes, causing an event to be emitted. |
patch.addHeader("Content-Type", "application/sparql-update"); | ||
patch.setEntity(new StringEntity( | ||
"INSERT { <> <http://purl.org/dc/elements/1.1/relation> <" + serverAddress + id1 + "> } WHERE {}")); | ||
try (final CloseableHttpResponse response = execute(patch)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't this just this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, thanks for catching that
@acoburn ok, that's what I thought but in creating an indirect container and adding an object to it, the membershipResource resource in Fedora gets the updated property but it does not seem to be "re-indexed" by the camel-toolbox. Perhaps it is my setup, I'll try and log the actual JMS messages coming out. |
@@ -61,10 +64,29 @@ public Container findOrCreate(final Session session, final String path) { | |||
|
|||
if (node.isNew()) { | |||
initializeNewObjectProperties(node); | |||
|
|||
final Node parent = node.getDepth() > 0 ? node.getParent() : null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Am I nuts or is this very much like what's new in BinaryServiceImpl
above?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I put this and several other instances of similar code into a single utility function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the dsNode
was created without a slug
and therefore the parent
is a PairTree, do we want to be touching the PairTree or the logical parent container? I suspect the latter.
Aside from sniping comments about code style and the like, this looks basically good to me. I mean, it's definitely the right direction. Just as a note to myself, the integration test for FedoraLdp is getting crazy long. I think we may need to break it up at some point. |
@whikloj you are right -- the eventing machinery is missing some changes related to indirect containers. Stay tuned for another commit related to that. |
@acoburn cool thanks. |
Is this ready? |
yes, please review/test |
return empty(); | ||
} | ||
|
||
public static Function<Session, Function<Resource, Optional<String>>> resourceToProperty = session -> resource -> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This might be clearer as a method:
public static Function<Resource, Optional<String>> resourceToProperty(Session session) {
- The only time you use it that I see, you explicitly call
apply
. That's the very semantic of a plain method, which is more concise. - The
Session
is actually part of the state of theResource -> Optional<String>
function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I previously changed it to a plain method and then changed it back for some reason (I don't recall exactly why). I'll see about changing to a plain method.
@ajs6f I have added another commit to address your most recent comments, along with a unit test for the |
Looks good to me. I'll wait a bit for other's comments. |
/me reviewing now |
* Check if a property is intentionally suppressed. | ||
*/ | ||
final static List<String> suppressed = Arrays.asList("jcr:mimeType", "jcr:lastModified"); | ||
private static Predicate<Property> isSuppressedProperty = uncheck(p -> suppressed.contains(p.getName())); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This Predicate does not appear to be used. If so, please remove.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@awoods this Predicate has been removed.
*/ | ||
public static void touchLdpMembershipResource(final Node node) throws RepositoryException { | ||
if (node.getDepth() > 0) { | ||
final Node parent = node.getParent(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This logic only works as expected if the parent
is the Direct/Indirect container... which is true if the node
was created with a slug
. However, in the common case where no slug
is used and the UUIDPathMinter creates the hierarchy, the true Direct/Indirect container does not get updated.
This can be demonstrated in an integration test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@awoods that is an excellent point. I wonder if reusing some of the code in FedoraResource::getContainer would be appropriate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FedoraResource::getContainer should resolve the issue.
@awoods I have addressed your comments in a new commit to this PR. |
if (createdDate != null) { | ||
LOGGER.trace("Using created date for last modified date for node {}", node); | ||
return createdDate; | ||
} | ||
|
||
return null; | ||
} | ||
private long getTimestamp(final String property, final long created) throws RepositoryException { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor: add a newline before this private
method.
I have addressed @awoods comments in a new commit. |
👍 Looks good. Any final words before we commit? |
Resolves: https://jira.duraspace.org/browse/FCREPO-1742
Resolves: https://jira.duraspace.org/browse/FCREPO-1498
Supersedes #917