package eu.europeana.cloud.service.coordination; import org.apache.curator.RetryPolicy; import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.CuratorFrameworkFactory; import org.apache.curator.retry.ExponentialBackoffRetry; import org.apache.curator.utils.EnsurePath; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import com.google.common.base.Throwables; /** * Enables and constantly monitors the communication with Zookeeper by managing * a connection to the ZooKeeper ensemble. * * @author emmanouil.koufakis@theeuropeanlibrary.org * */ @Component public class ZookeeperService { /** Logging */ private static final Logger LOGGER = LoggerFactory.getLogger(ZookeeperService.class); /** Enables the communication with the ZooKeeper ensemble. */ private final CuratorFramework zkClient; /** * If the connection is temporarily lost, Curator will attempt to retry the operation * until it succeeds per the currently set retry policy. */ private final static RetryPolicy ZOOKEEPER_RETRY_POLICY = new ExponentialBackoffRetry( 1000, 3 ); /** Base path where all services are registered. */ private final String zookeeperPath; /** * */ public ZookeeperService(final String zookeeperAddress, final int zookeeperConnectionTimeout, final int zookeeperSessionTimeout, final String zookeeperPath) { LOGGER.info("ZookeeperService starting..."); this.zookeeperPath = zookeeperPath; zkClient = CuratorFrameworkFactory.builder() .connectionTimeoutMs(zookeeperConnectionTimeout) .retryPolicy(ZOOKEEPER_RETRY_POLICY) .sessionTimeoutMs(zookeeperSessionTimeout) .connectString(zookeeperAddress).build(); zkClient.start(); // ZooKeeper paths must be explicitly created // Let's make sure the path exists try { new EnsurePath(zookeeperPath).ensure(zkClient.getZookeeperClient()); LOGGER.info("ZookeeperService started successfully."); } catch (final Exception e) { LOGGER.error("ZooKeeper base path '{}' not found... Exception='{}'. " + " The path must be manually created in zookeeper," + " and is needed for configuration settings retrieval and service registration." , zookeeperPath, e.getMessage()); throw Throwables.propagate(e); } } /** * @return Base path where all services are registered. */ public String getZookeeperPath() { return zookeeperPath; } public CuratorFramework getClient() { return zkClient; } }