All Downloads are FREE. Search and download functionalities are using the official Maven repository.

pl.allegro.tech.hermes.infrastructure.zookeeper.cache.HierarchicalCache Maven / Gradle / Ivy

There is a newer version: 2.7.0
Show newest version
package pl.allegro.tech.hermes.infrastructure.zookeeper.cache;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent;
import org.apache.zookeeper.KeeperException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import pl.allegro.tech.hermes.common.exception.InternalProcessingException;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.ExecutorService;
import java.util.function.BiFunction;
import java.util.function.Consumer;

public class HierarchicalCache {

    private static final Logger logger = LoggerFactory.getLogger(HierarchicalCache.class);

    private final CuratorFramework curatorFramework;

    private final ExecutorService executorService;

    private final String basePath;
    private final boolean removeNodesWithNoData;

    private final List levelPrefixes = new ArrayList<>();

    private final int maxDepth;

    private final List levelCallbacks = new ArrayList<>();

    private HierarchicalCacheLevel rootCache;

    public HierarchicalCache(CuratorFramework curatorFramework,
                             ExecutorService executorService,
                             String basePath,
                             int maxDepth,
                             List levelPrefixes,
                             boolean removeNodesWithNoData) {
        this.curatorFramework = curatorFramework;
        this.executorService = executorService;
        this.basePath = basePath;
        this.removeNodesWithNoData = removeNodesWithNoData;
        this.levelPrefixes.addAll(levelPrefixes);
        this.maxDepth = maxDepth;

        for (int i = 0; i < maxDepth; ++i) {
            levelCallbacks.add(new CacheListeners());
        }
    }

    public void start() throws Exception {
        ensureBasePath();
        rootCache = createLevelCache(0, basePath);
    }

    public void stop() throws Exception {
        rootCache.stop();
    }

    public void registerCallback(int depth, Consumer callback) {
        levelCallbacks.get(depth).addListener(callback);
    }

    private HierarchicalCacheLevel createLevelCache(int depth, String path) {
        BiFunction function = depth + 1 < maxDepth ? this::createLevelCache : null;
        HierarchicalCacheLevel levelCache = new HierarchicalCacheLevel(curatorFramework,
                executorService,
                path(depth, path),
                depth,
                levelCallbacks.get(depth),
                Optional.ofNullable(function),
                removeNodesWithNoData);
        try {
            logger.debug("Starting hierarchical cache level for path  {} and depth {}", path, depth);
            levelCache.start();
        } catch (Exception e) {
            logger.error("Failed to start hierarchical cache level for path {} and depth {}", path(depth, path), depth, e);
        }
        return levelCache;
    }

    private String path(int depth, String basePath) {
        return basePath + (levelPrefixes.size() > depth ? "/" + levelPrefixes.get(depth) : "");
    }

    private void ensureBasePath() {
        try {
            try {
                if (curatorFramework.checkExists().forPath(basePath) == null) {
                    curatorFramework.create().creatingParentsIfNeeded().forPath(basePath);
                }
            } catch (KeeperException.NodeExistsException e) {
                // ignore
            }
        } catch (Exception e) {
            throw new InternalProcessingException(e);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy