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

[CAMEL-17481] Caffeine cache improvements #6728

Merged
merged 2 commits into from Jan 14, 2022

Conversation

ank19
Copy link
Contributor

@ank19 ank19 commented Jan 12, 2022

Pls. refer to the CAMEL-17481 issue for details.

Please note that before Camel 3.15 the invalidate all action (CaffeineConstants.ACTION_INVALIDATE_ALL) does not
delete anything in case that CaffeineConstants.KEYS header is either missing or contains an empty set.

Starting vom Camel 3.15 the invalidate all action does not delete anything in case the CaffeineConstants.KEYS header
Copy link
Contributor

Choose a reason for hiding this comment

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

vom -> from

Copy link
Contributor

Choose a reason for hiding this comment

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

I think we should move this section to the migration guide, since we are producing docs for each of the active branches

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah yeah that is better as if you use camel 3.14 or older then you read the docs for that version which does not have this change. So yeah this should be moved to the 3.15 upgrade guide in the root/docs folder

Please note that before Camel 3.15 the invalidate all action (CaffeineConstants.ACTION_INVALIDATE_ALL) does not
delete anything in case that CaffeineConstants.KEYS header is either missing or contains an empty set.

Starting vom Camel 3.15 the invalidate all action does not delete anything in case the CaffeineConstants.KEYS header
Copy link
Contributor

Choose a reason for hiding this comment

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

same here

if (ObjectHelper.isEmpty(configuration.getStatsCounter())) {
builder.recordStats();

synchronized (this) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a reason for using sync block here? A given endpoint instance is started only once and not concurrently

Copy link
Contributor

Choose a reason for hiding this comment

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

+1, no need for sync

Copy link
Contributor

@oscerd oscerd left a comment

Choose a reason for hiding this comment

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

Just some comments and some discussions. Thanks for the PR.

Please note that before Camel 3.15 the invalidate all action (CaffeineConstants.ACTION_INVALIDATE_ALL) does not
delete anything in case that CaffeineConstants.KEYS header is either missing or contains an empty set.

Starting vom Camel 3.15 the invalidate all action does not delete anything in case the CaffeineConstants.KEYS header
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we should move this section to the migration guide, since we are producing docs for each of the active branches

if (ObjectHelper.isEmpty(configuration.getStatsCounter())) {
builder.recordStats();

synchronized (this) {
Copy link
Contributor

Choose a reason for hiding this comment

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

+1, no need for sync

builder.removalListener(configuration.getRemovalListener());
}
cache = builder.build();
getCamelContext().getRegistry().bind(cacheName, Cache.class, cache);
Copy link
Contributor

Choose a reason for hiding this comment

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

If you don't set the cache in the registry before the endpoint has been started, there is no mean of doing this after you create it in the doStart. If you don't set the cache instance in the registry, you'll use the cache created in the doStart for the lifecycle of the endpoint.

The toF examples are an attempt to explain that if you use a pure to without a cache in the registry you'll get just a cache created in the lifecycle of the endpoint, this means you won't be able to reuse it in a different endpoint. Binding the cache to the registry in the doStart is wrong in my opinion.

Copy link
Contributor Author

@ank19 ank19 Jan 13, 2022

Choose a reason for hiding this comment

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

Ah, ok - I think I got your point. However, might it be that the documentation is misleading and the associated test case is wrong? As it just works with .toF() without prior initialization? The problem with the test case is IMHO that if the GET command returns null, the body is not set, as there's a null check in that action. That in turn means that the body value from the PUT action before is still set and therefore the test succeeds, but not because the same cache is used.

Basically

	    camelContext.getRegistry().bind("cache", Caffeine.newBuilder().build());

            from("direct://start")

                .to("caffeine-cache://cache?action=PUT&key=1")
		.setBody(constant("")) // test case fix to illustrate the issue
                .to("caffeine-cache://cache?key=1&action=GET")
                .log("Test! ${body}")
                .to("mock:result");

instead of

            from("direct://start")

                .to("caffeine-cache://cache?action=PUT&key=1")
                .to("caffeine-cache://cache?key=1&action=GET")
                .log("Test! ${body}")
                .to("mock:result");

I don't dare to say whether or not binding a cache to the registry within the endpoint fits to the Camel concept, but it doesn't, the synchronization indeed doesn't make sense at all, of course. Otherwise a synchronization would be required I guess, but according to my tests it has to be something like synchronized (getCamelContext().getRegistry()) instead of a synchronized(this), which is probably a very expensive lock and would have to be mitigated by double-check idiom or so. Thinking of it, I guess the binding looks somehow complicated - you're right and the cache has to be created before using it. Can you confirm? Then I try to update the pull request asap.

Copy link
Contributor

Choose a reason for hiding this comment

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

Essentialy the cache needs to be created ahead of the enbpoint instantiation and start, so it should be in the registry before. You're, by the way, welcome to test and improve the component :-) Thanks a lot!

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 have to say thanks for the valuable comments! Took me a while to grasp it, but hopefully I got it now, :-) I removed the binding/sync part and I added

@BindToRegistry("cache")
Cache cache = Caffeine.newBuilder().recordStats().build();

to the documentation to illustrate it, hope that's fine - I guess that was my missing link in understanding.

if (ObjectHelper.isEmpty(configuration.getStatsCounter())) {
builder.recordStats();

synchronized (this) {
Copy link
Contributor

Choose a reason for hiding this comment

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

No need for sync

@ank19 ank19 requested a review from oscerd January 13, 2022 17:58
Copy link
Contributor

@oscerd oscerd left a comment

Choose a reason for hiding this comment

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

Thanks. Looks really good.

Sorry sometimes when I write about Camel I take some concepts for granted and I might be a bit criptic.

@davsclaus
Copy link
Contributor

Is this PR good to be merged?

@oscerd
Copy link
Contributor

oscerd commented Jan 14, 2022

Yes

@davsclaus davsclaus merged commit a402c15 into apache:main Jan 14, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants