package microservices.sample.user; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.collect.Sets; import com.google.inject.Singleton; import microservices.sample.ServiceBuilder; import microservices.sample.discovery.PublishedServiceInfo; import microservices.sample.discovery.ServiceDiscoveryListener; import microservices.sample.persistence.PersistenceService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; /** * PersistenceService provider using Retrofit. * <p> * This class listens to ServiceDiscovery events and keeps track of available services of type PersistenceService. * * @author mamad * @since 17/03/15. */ @Singleton public class AutoDiscoveryPersistenceServiceProvider implements PersistenceServiceProvider, ServiceDiscoveryListener { private static final Logger LOGGER = LoggerFactory.getLogger(AutoDiscoveryPersistenceServiceProvider.class); private static final CacheLoader<String, PersistenceService> CACHE_LOADER = new CacheLoader<String, PersistenceService>() { @Override @SuppressWarnings("unchecked") public PersistenceService load(String url) throws Exception { return ServiceBuilder.create(PersistenceService.class).build(url); } }; private final Set<PublishedServiceInfo<PersistenceService>> availableServices = Sets.newConcurrentHashSet(); private final String persistenceServiceVersion; private Cache<String, PersistenceService> serviceCache = CacheBuilder.newBuilder() .expireAfterAccess(10, TimeUnit.MINUTES) .build(CACHE_LOADER); public AutoDiscoveryPersistenceServiceProvider(String persistenceServiceVersion) { this.persistenceServiceVersion = persistenceServiceVersion; } @Override public PersistenceService get() { Optional<PublishedServiceInfo<PersistenceService>> optional = availableServices .stream() .filter(info -> Objects.equals(info.getVersion(), persistenceServiceVersion)) .findAny(); if (!optional.isPresent()) { throw new RuntimeException("No service available"); } PublishedServiceInfo<PersistenceService> info = optional.get(); String url = String.format("http://%s:%d", info.getIp(), info.getPort()); try { return serviceCache.get(url, () -> CACHE_LOADER.load(url)); } catch (ExecutionException e) { LOGGER.error("Error in creating persistence service for url:{}", url, e); return null; } } @Override @SuppressWarnings("unchecked") public <S> void onServiceJoined(PublishedServiceInfo<S> info) { if (PersistenceService.class.equals(info.getServiceClass())) { availableServices.add((PublishedServiceInfo<PersistenceService>) info); } } @Override @SuppressWarnings("unchecked") public <S> void onServiceLeft(PublishedServiceInfo<S> info) { if (PersistenceService.class.equals(info.getServiceClass())) { availableServices.remove(info); } } }