-1

I have create a cache using google guava cache

here is my implementation of it

private final LoadingCache<Long, DistChannel> channelServiceCache = CacheBuilder.newBuilder().maximumSize(50)
        .refreshAfterWrite(4, TimeUnit.HOURS).build(new CacheLoader<Long, DistChannel>() {

            @Override
            public DistChannel load(Long channelId) throws InvalidRequestException, TException {
                long start = System.nanoTime();
                try {
                    return channelService.getDistributionChannelById(channelId, SOLR_API_KEY);
                } catch (InvalidRequestException e) {
                    log.error("Cannot look up channel: {}", channelId, e);
                    String serviceName = StringUtils.isNotBlank(e.getServiceName()) ? e.getServiceName() : CHANNEL_SERVICE;
                    throw e.setServiceName(serviceName + "." + SERVICE_NAME + "." + hostName);
                } finally {
                    log.info("Channel Service call, ChannelId: {} Time : {}", channelId,
                            TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start));
                }
            }


            @Override
            public ListenableFuture<DistChannel> reload(final Long channelId, final DistChannel oldValue) throws Exception {
                ListenableFutureTask<DistChannel> task = ListenableFutureTask.create(new Callable<DistChannel>() {
                    public DistChannel call() {
                        long start = System.nanoTime();
                        try {
                            return channelService.getDistributionChannelById(channelId, SOLR_API_KEY);
                        } catch (TException e) {
                            log.error("Cannot look up channel: {}", channelId, e);
                        }finally {
                            log.info("reload Channel Service call, ChannelId: {} Time : {}", channelId,
                                    TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start));
                        }
                        return oldValue;
                    }
                });
                executorServiceForCache.execute(task);
                return task;
            }

        });

now in channelService.getDistributionChannelById method, I need to paas two values namely channelId and apiKey.

Currently its working fine as apiKey is constant. But now apiKey is modified to this contant ~ timestamp. for example:

SOLR_API_KEY~123456789

So My Problem is:

How can I pass one more parameter in channelServiceCache.get(key, extraparam here) without modifying the key.

Thing which I tried : I created a Key object in which my actual key as well as apiKey will be present and pass that as key in channelServiceCache But this will kill the purpose of cache as every kill will be considered a new key as it contains timestamp in apikey.

Is there any way I can do this with google guava?

EDIT : One more thing which I missed:

service will give same output for same channelId, API key is only used for authentication and logging and monitoring request counts. But I guess it makes sense, If I can serve next request with same channelID from cache, then apiKey will never be passed to actual service (where actual logging and monitoring is taking place.) Is there any other way to implement this functionality without actually killing purpose of google guava.

Boola
  • 358
  • 3
  • 14
  • 1
    Your problem definition seems inconsistent. Based on your description, one could answer your requirement by implementing a Key class, that holds both the channel id and API Key, but implements hashCode and equals soleloy based on the channel id. **BUT** why on earth would it be usefull : there is a reason why your channelService needs both arguments to fullfill its contract. If you can reuse the channel ID no matter what the API Key is, then why would you need it in the first place ? – GPI Jun 21 '16 at 12:57
  • I can reuse it but its not constant value. – Boola Jun 21 '16 at 13:07

1 Answers1

3

If the output of the service is different for each channel id and API Key, then the API key needs to be part of the cache key.

If the output is identical no matter what API key, then you can use any API key or the always the same API key.

Passing down the API key from the caller, but caching the value does make no sense, or is essentially identically to randomly choose an API key. As soon as the value is in the cache, you will return a result that was retrieved with a different API key from the previous caller.

cruftex
  • 5,545
  • 2
  • 20
  • 36
  • No, service will give same output for same channelId, API key is only used for authentication and logging and monitoring request counts. – Boola Jun 21 '16 at 13:02
  • 1
    Agreed with @cruftex. If `service` uses the APIKey for *any* purpose, then it is part of your cache key. Ex : you ask a new "channel" for `id=1, apiK=1`. `channelService.getDistributionChannelById` is called, it perfoms "logging" for `apiKey=1`, you get your `DistChannel` object. Then you request another for `id=1, apiKey=2`. The cache, according to you, should bring back the same `DistChannel` instance. So `channelService.getDistributionChannelById` should not be called, and its logging for apiKey=2 should never occur. Conclusion : you don't need it / might as well use any random value. – GPI Jun 21 '16 at 13:20
  • Turns out, my requirements were exactly what you said. Thanks for pointing out this @GPI – Boola Jun 22 '16 at 07:08