2

Suppose I have an authorization session store implemented as a Cache<String, Session>, where Cache is Guava cache or something similar and Session is some map-like object with session data. Suppose the keys are some sessionId strings generated during the initial authentication. The cache itself has some expiry strategy so that, for example, after 30m of inactivity a session gets evicted and a callback with two arguments, the cache key and cache value is eventually called for a full clean-up.

Suppose now I want to map different login options of essentially the same user to the same sessionId. For example, a follow up request can be made with the same login credentials which should resolve to already present session, or an API request that is linked to the same user can be placed or a browser can ask for data using the session Id in its cookie -- all of those should resolve to the same session and session Id.

One strategy to implement this would be to maintain a Map<String, String> from the original authorization header (or some hash of it) to the sessionId and then go to the original cache. This one can be a simple map for which a missing value would be identical to a situation where there is a value but not corresponding session in the session cache. I could eventually clean-up all the entries matching the same sessionId when the session cache expiry callback is called. This solution is straightforward to implement, but it is a bit ugly.

Another strategy, much more appealing to me, would be to actually use the original authorization header (or some hash of it) along with the sessionId as the key for the session cache pointing to exactly the same session (so multiple keys, at least two, pointing to the same session value). Adding data is trivial, but eviction is tricky as all key-value pairs for the same session (value) must be evicted at once and the callback must be called just once (as some finalization logic should be executed for the session, but only once).

Any suggestion for existing caching libraries supporting such functionality or any ideas how to implement the idea on top of e.g. Guava Cache or any similar caching solution?

Oleg Sklyar
  • 9,834
  • 6
  • 39
  • 62
  • I can not think of a solution. But take a look at some similar questions Q1: [Java: How to get set of keys having same value in hashmap](https://stackoverflow.com/q/12710494/1429387), Q2: [Guava combination of Multimap and Cache](https://stackoverflow.com/q/9566568/1429387) – naXa stands with Ukraine Apr 26 '18 at 14:14
  • Thanks for suggestions, unfortunately won't bring me further. As for Q1 I know the answer myself, but the problem is that the `removalHandler` in Guava is called **eventually** so when one of the keys is evicted, its removal handler cannot be used to eliminate all other. As for Q2, the problem is the other way round. – Oleg Sklyar Apr 26 '18 at 14:17
  • A [similar](https://github.com/ben-manes/caffeine/issues/234#issuecomment-384487699) question came up for Caffeine, a Guava-like cache. For properly handling capacity constraints, etc. I'd go with a `key=>primaryKey` map tied to the `primaryKey=>value` cache – Ben Manes Apr 26 '18 at 16:20
  • @BenManes Thanks. Given responses this seems to be a simple and pragmatic solution even if not so elegant :) – Oleg Sklyar Apr 26 '18 at 20:11
  • 1
    Actually, you could do your approach if you set the weight to zero and, if using Caffeine's `Expiry`, to never expire. If you can detect the key is secondary, then the cache policies will only apply to the primary. Could work, but do note that computations (e.g. `load(key)`) should not call back into the cache (recursion is prohibited by `ConcurrentHashMap`) so you would have to populate the additional mappings asynchronously. – Ben Manes Apr 26 '18 at 20:16
  • @BenManes I saw your GitHub comment first: thanks for a suggestion. I actually have a fully async cache based on Completable Futures as a wrapper around Guava LoadingCache and the idea with weights might work the same way with the Guava implementation. I will give it a thought and a try – Oleg Sklyar Apr 26 '18 at 20:30
  • I wrote it after I wrote the above =) – Ben Manes Apr 26 '18 at 20:31

0 Answers0