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

QueryCache improvements for local caching #292

Closed
wants to merge 4 commits into from

Conversation

johnthuss
Copy link
Contributor

Added getQueryCache to the ObjectContext interface since this is already implemented by BaseContext anyway and makes accessing the cache much easier.

Revised signature for QueryCache.remove(String) to be remove(QueryMetadata) to increase understandability. It was never clear how to use this method before.

Added QueryCache.clearLocalCache method. This is now called automatically at the end of the request-response loop in StatelessContextRequestHandler and by BaseContext.finalize. This will prevent memory leaking from locally cached data in cases where the cache is not configured to expire entries based on time.

Added QueryCache.debugListCacheKeys method to list all keys (prefixed by cache group) in the cache for debugging purposes.

johnthuss and others added 2 commits May 2, 2018 10:27
…ady implemented by BaseContext anyway and makes accessing the cache much easier.

Revised signature for QueryCache.remove(String) to be remove(QueryMetadata) to increase understandability. It was never clear how to use this method before.

Added QueryCache.clearLocalCache method. This is now called automatically at the end of the request-response loop in StatelessContextRequestHandler and by BaseContext.finalize. This will prevent memory leaking from locally cached data in cases where the cache is not configured to expire entries based on time.

Added QueryCache.debugListCacheKeys method to list all keys (prefixed by cache group) in the cache for debugging purposes.
@johnthuss
Copy link
Contributor Author

It looks like the build failed just because it stalled on the last case. Is there a way to re-run it without adding another commit?

@stariy95
Copy link
Member

stariy95 commented May 8, 2018

Hi @johnthuss, I prefer not to bother with random glitches in travis (or docker) as long as it only a single failure.

if (key != null) {
for (String cache : cacheManager.getCacheNames()) {
getCache(cache).remove(key);
public void remove(QueryMetadata metadata) {
Copy link
Member

Choose a reason for hiding this comment

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

I believe we should keep old method for backward compatibility as it is part of public API (it may be marked as @Deprecated and deleted in a later release).
Also we try to mark all new public API methods with javadoc annotation @since CURRENT_VERSION.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for your comments. I thought that would be the case.

}

@Override
public List<String> debugListCacheKeys() {
Copy link
Member

Choose a reason for hiding this comment

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

Don't think this should in public API, we don't provide any tools to manage cache anyway. If someone need this, javax.cache.CacheManager can be injected and analyzed directly. Or, even better, specialized tools of actual JCache provider can be used.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm not sure how injection could change this as the NestedQueryCache is hardcoded to wrap whatever cache is used. So to access the real cache directly you have to cast to NestedQueryCache and call getDelegate. But I guess that works, so I agree.

}

@Override
public List<String> debugListCacheKeys() {
Copy link
Member

Choose a reason for hiding this comment

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

Don't think this should be part of public API, we don't provide any tools to manage cache (and we probably shouldn't). If someone need this, javax.cache.CacheManager can be injected and analyzed directly. Or, even better, specialized tools of actual JCache provider can be used.

@@ -67,6 +69,10 @@ public void requestStart(ServletRequest request, ServletResponse response) {

public void requestEnd(ServletRequest request, ServletResponse response) {
CayenneRuntime.bindThreadInjector(null);
ObjectContext context = BaseContext.getThreadObjectContext();
if (context != null) {
((BaseContext)context).getQueryCache().clearLocalCache(Optional.empty());
Copy link
Member

Choose a reason for hiding this comment

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

Don't like this Optional.empty() thing, it's a little bit obscure what is it doing and why it's always empty.
Maybe we can push it directly to NestedQueryCache and call it explicitly from contexts that actually use it, but then we'll need some sort of context.cleanup() call.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't like it either. The QueryCache interface doesn't have any concept of namespacing like the NestedQueryCache does, so any change that needs to target just the local cache and not shared&local must by necessity introduce something that represents the namespace or local/shared distinction. So I'm open to ideas. I'm not sure that NestedQueryCache really needs to exists as a separate class at all. The namespacing could be combined into to JCacheQueryCache as long as the QueryCache interface methods all support distinguishing between shared/local cache strategies, which it mostly does with this. The exception is removeGroup, which targets both shared and local, but that is probably fine as long as it is documented. I think combining NestedQueryCache would be my next choice.

@johnthuss
Copy link
Contributor Author

I made changes based on your feedback. I left the debugListCacheKeys method in JCacheQueryCache but removed it from the QueryCache interface. The only alternative would be to expose the CacheManager directly, which would work if you prefer that.

I don't know how to remove the Optional.empty() thing as I described above. The JCacheQueryCache.clearLocalCache method needs to know the namespace value from NestedQueryCache which it has no access to.

@johnthuss
Copy link
Contributor Author

Any more comments on this? I'd like to keep moving it forward.

@johnthuss
Copy link
Contributor Author

I'm going to close this and push something with a different approach. The LOCAL query cache should be able to be separate from the SHARED query cache in order to have an independent lifecycle (i.e. one that matches the ObjectContext it is connected to).

@johnthuss johnthuss closed this Jun 11, 2019
@johnthuss johnthuss reopened this Jul 9, 2019
@johnthuss
Copy link
Contributor Author

These commits need some updates now, but it is a start in the direction we discussed on the dev mailing list. There are a few independent changes here, it's not all just about handling memory/invalidation, see my first comment for more info.

@johnthuss johnthuss closed this Apr 3, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants