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

Introduce CacheKeyGenerator #25844

Merged
merged 1 commit into from Jun 1, 2022

Conversation

gwenneg
Copy link
Member

@gwenneg gwenneg commented May 29, 2022

Fixes #23515
Fixes #25588

See the doc update for details about CacheKeyGenerator.

Copy link
Contributor

@geoand geoand left a comment

Choose a reason for hiding this comment

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

Very nice improvement!

I added some docs related comments. I also think that a review from @mkouba would be beneficial

@gwenneg gwenneg force-pushed the issue-23515-cache-key-generator branch 2 times, most recently from 8bb2f9a to 7d0a13e Compare May 30, 2022 09:16
@gastaldi gastaldi requested a review from mkouba May 31, 2022 00:51
You may want to include more than the arguments of a method into a cache key.
This can be done by implementing the `io.quarkus.cache.CacheKeyGenerator` interface and declaring that implementation in the `keyGenerator` field of a `@CacheResult` or `@CacheInvalidate` annotation.

If a CDI scope is declared on a key generator, then it will be injected as a CDI bean during the cache key computation.
Copy link
Contributor

Choose a reason for hiding this comment

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

So I suppose that only class-based managed beans are supported, right? I.e. no producers or synthetic beans.

Also it seems that you don't take CDI qualifiers into account at runtime and so you should probably forbid the usage of custom qualifiers, or just mention that the default qualifier must be used (in CDI this means either no qualifier annotation or @javax.enterprise.inject.Default).

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, the key generators are restricted to class-based managed beans because we need to declare the keygen class in the caching annotations.

Qualifiers should be forbidden indeed and/or documented.

// Key generators must have a default constructor if they are not managed by Arc.
private List<Throwable> validateKeyGeneratorsDefaultConstructor(CombinedIndexBuildItem combinedIndex,
BeanDiscoveryFinishedBuildItem beanDiscoveryFinished, Set<DotName> keyGenerators) {
List<DotName> managedBeans = beanDiscoveryFinished.geBeans()
Copy link
Contributor

Choose a reason for hiding this comment

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

If only managed beans are supported then you should filter out unsupported bean types, i.e. beanDiscoveryFinished.geBeans().stream().filter(BeanInfo::isClassBean).

@@ -138,6 +146,30 @@ protected Object getCacheKey(Cache cache, List<Short> cacheKeyParameterPositions
}
}

private Object generateKey(Class<? extends CacheKeyGenerator> keyGeneratorClass, Method method,
Object[] methodParameterValues) {
InstanceHandle<? extends CacheKeyGenerator> keyGeneratorHandle = Arc.container().instance(keyGeneratorClass);
Copy link
Contributor

Choose a reason for hiding this comment

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

You can @Inject Instance<CacheKeyGenerator> directly in the interceptor and then use instance.select(keyGeneratorClass) and Instance#isResolvable() and Instance#get() instead. This way you would not need to produce an UnremovableBeanBuildItem for all the CacheKeyGenerator implementations and moreoever @Dependent scoped impls would be correctly bound the lifecycle of the interceptor.

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 will still need to call Instance#destroy on the keygen instance after I'm done generating the cache key, right? I just tested your suggestion (which is great, thanks!) without calling destroy locally and the instances of CacheKeyGenerator are piling up in the memory.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, for @Dependent keygens you'd need to call destroy() or even @Inject io.quarkus.arc.InjectableInstance<CacheKeyGenerator> and use getHandle() to obtain an io.quarkus.arc.InstanceHandle which also extends AutoCloseable.

@gwenneg gwenneg force-pushed the issue-23515-cache-key-generator branch from 7d0a13e to 8db4a5b Compare May 31, 2022 13:30
@gwenneg
Copy link
Member Author

gwenneg commented May 31, 2022

@mkouba I pushed a commit that should cover all your comments. Does the PR look better now?

Copy link
Contributor

@mkouba mkouba left a comment

Choose a reason for hiding this comment

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

Looks good! :-)

@gwenneg
Copy link
Member Author

gwenneg commented Jun 1, 2022

Thanks everyone for the reviews!

@geoand geoand merged commit d921f97 into quarkusio:main Jun 1, 2022
@quarkus-bot quarkus-bot bot added this to the 2.10 - main milestone Jun 1, 2022
@quarkus-bot quarkus-bot bot added the kind/enhancement New feature or request label Jun 1, 2022
@gwenneg gwenneg deleted the issue-23515-cache-key-generator branch June 1, 2022 07:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
4 participants