I don't think that the RR is the right place for this.

If the use case is that during a request the exact same query is executed more than once, then caching the result of the query in Sling is probably not resulting in the wanted gain. I think it is much better to avoid executing the query multiple times in the first place - executing the query is one part but then processing the result is another. And you want to avoid this as well.

In the past 12 years or so we tried various POCs with caching in the RR. Always under the (wrong) assumption that Oak/Jackrabbit is the bottleneck. So we added a RR caching all get resources, all list resources, all queries etc. And it turned out that the gain was close to zero. Each operation in Oak was pretty fast, but if you execute it hundreds of times during a request, even a fast call becomes the bottleneck. So again, usually the problem is in the upper layers, above Sling's resource api.

Now, lets assume, you want to cache in the RR - this becomes quickly very tricky. When do you clear/update the cache? The quick answer is usually "we cache per request" - which already comes with the first problem, how do you know that a RR is bound to a request? But even if you manage to find this out, there are methods which perform modifications, so you need to update the cache based on them. Similar there is RR refresh(), especially used by long running RRs where you want to clear the cache. But implementing this in the RR is not sufficient as the resource api might be bypassed and JCR API might be directly used. Or in other words, maintaining the cache correctly is impossible in the RR layer.

So, if things need to be cached, this should be done in Oak/Jackrabbit. This is the only place where you know about all operations and can deal with the cache appropriately.

If caching something in the RR really provides benefits and does not create headaches, then the resource provider API already provides all you need. Stateful resource providers like the JCR one maintain a state object per resource resolver; for JCR this basically holds the JCR session but it can be extended to hold a cache or similar, too. The state object is discarded along with the RR.

In summary:
- avoid redundant calls in the first place
- if needed, cache at the right place (Oak)
- state can be maintained per RR without any api addition

Regards
Carsten
Am 11.10.2021 um 16:18 schrieb Jörg Hoh:
Hi,

I am investigating a reasonable way to cache objects which have the same
livecycle as a resource resolver, because they are retrieved or derived
from it.
For example this could be the result of query, which is used at multiple
locations within my application, all in the context of the same request /
resource resolver. Right now my only way is to store them in request
attributes, but that does not feel right, because it rather relates to the
resource resolver (and not the request itself), and it requires me to pass
always the request along although I just need the resource resolver. Also
in some situations there is alrady existing code, which just passes along
the resource resolver and no request (maybe the operation does not even
work in the context of a request).

I checked the API of the ResourceResolver, and it comes with
getAttributeNames() and getAttribute(), but these properties are populated
during creation and cannot be modified afterwards. So not helpful here.

I envision to have a WeakHashMap<String,Object>, which can be reached via a
new API call "getTemporaryStorage()" (I am very open for a better name),
which we could implement as default method right in the interface.

WDYT?




--
Carsten Ziegeler
Adobe
[email protected]

Reply via email to