/** * Copyright 2016 Hortonworks. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. **/ package com.hortonworks.registries.schemaregistry.client; import com.google.common.base.Preconditions; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.hortonworks.registries.schemaregistry.SchemaMetadataInfo; import com.hortonworks.registries.schemaregistry.errors.SchemaNotFoundException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; /** * */ public class SchemaMetadataCache { private static final Logger LOG = LoggerFactory.getLogger(SchemaMetadataCache.class); private final LoadingCache<Key, SchemaMetadataInfo> loadingCache; public SchemaMetadataCache(Long size, Long expiryInSecs, final SchemaMetadataFetcher schemaMetadataFetcher) { loadingCache = CacheBuilder.newBuilder() .maximumSize(size) .expireAfterAccess(expiryInSecs, TimeUnit.SECONDS) .build(new CacheLoader<Key, SchemaMetadataInfo>() { @Override public SchemaMetadataInfo load(Key key) throws Exception { if (key.getName() != null) { return schemaMetadataFetcher.fetch(key.getName()); } else if (key.getId() != null) { return schemaMetadataFetcher.fetch(key.getId()); } else { throw new IllegalArgumentException("Key should have name or id as non null"); } } }); } public SchemaMetadataInfo get(Key key) { SchemaMetadataInfo schemaMetadataInfo; try { schemaMetadataInfo = loadingCache.get(key); } catch (ExecutionException e) { LOG.error("Error occurred while retrieving schema metadata for [{}]", key, e); Throwable cause = e.getCause(); if (!(cause instanceof SchemaNotFoundException)) { throw new RuntimeException(cause.getMessage(), cause); } schemaMetadataInfo = null; } return schemaMetadataInfo; } public SchemaMetadataInfo getIfPresent(Key key) { return loadingCache.getIfPresent(key); } public interface SchemaMetadataFetcher { SchemaMetadataInfo fetch(String name) throws SchemaNotFoundException; SchemaMetadataInfo fetch(Long id) throws SchemaNotFoundException; } public static class Key { private String name; private Long id; private Key(String name) { Preconditions.checkNotNull("name can not be null", name); this.name = name; } private Key(Long id) { Preconditions.checkNotNull("id can not be null", id); this.id = id; } public String getName() { return name; } public Long getId() { return id; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Key key = (Key) o; if (name != null ? !name.equals(key.name) : key.name != null) return false; return id != null ? id.equals(key.id) : key.id == null; } @Override public int hashCode() { int result = name != null ? name.hashCode() : 0; result = 31 * result + (id != null ? id.hashCode() : 0); return result; } public static Key of(String name) { return new Key(name); } public static Key of(Long id) { return new Key(id); } } }