private NodeCache makeNodeCache(final ServiceInstance<T> instance) { if (!watchInstances) { return null; } final NodeCache nodeCache = new NodeCache(client, pathForInstance(instance.getName(), instance.getId())); try { nodeCache.start(true); } catch (Exception e) { log.error("Could not start node cache for: " + instance, e); } NodeCacheListener listener = new NodeCacheListener() { @Override public void nodeChanged() throws Exception { if (nodeCache.getCurrentData() != null) { ServiceInstance<T> newInstance = serializer.deserialize(nodeCache.getCurrentData().getData()); Entry<T> entry = services.get(newInstance.getId()); if (entry != null) { synchronized (entry) { entry.service = newInstance; } } } else { log.warn("Instance data has been deleted for: " + instance); } } }; nodeCache.getListenable().addListener(listener); return nodeCache; }
@Override public void updateService(final ServiceInstance<T> service) throws Exception { Entry<T> entry = services.get(service.getId()); if (entry == null) { throw new Exception("Service not registered: " + service); } synchronized (entry) { entry.service = service; byte[] bytes = serializer.serialize(service); String path = pathForInstance(service.getName(), service.getId()); client.setData().forPath(path, bytes); } }
@VisibleForTesting protected void internalRegisterService(ServiceInstance<T> service) throws Exception { byte[] bytes = serializer.serialize(service); String path = pathForInstance(service.getName(), service.getId()); final int MAX_TRIES = 2; boolean isDone = false; for (int i = 0; !isDone && (i < MAX_TRIES); ++i) { try { CreateMode mode = (service.getServiceType() == ServiceType.DYNAMIC) ? CreateMode.EPHEMERAL : CreateMode.PERSISTENT; client.create().creatingParentsIfNeeded().withMode(mode).forPath(path, bytes); isDone = true; } catch (KeeperException.NodeExistsException e) { client.delete().forPath(path); // must delete then re-create so that watchers fire } } }