@Override public <S extends StreamDefinition> S save(S entity) { try { Map<String, String> map = new HashMap<>(); map.put(DEFINITION_KEY, entity.getDefinition()); map.put( MODULE_DEFINITIONS_KEY, objectWriter.writeValueAsString(entity.getModuleDefinitions())); CuratorFramework client = zkConnection.getClient(); String path = Paths.build(Paths.STREAMS, entity.getName()); byte[] binary = ZooKeeperUtils.mapToBytes(map); BackgroundPathAndBytesable<?> op = client.checkExists().forPath(path) == null ? client.create() : client.setData(); op.forPath(path, binary); logger.trace("Saved stream {} with properties {}", path, map); StreamDefinitionRepositoryUtils.saveDependencies(moduleDependencyRepository, entity); } catch (Exception e) { // NodeExistsException indicates that we tried to create the // path just after another thread/jvm successfully created it ZooKeeperUtils.wrapAndThrowIgnoring(e, NodeExistsException.class); } return entity; }
/** * Test the usage of {@link StreamDeploymentsPath} when providing the entire path. Assert that the * path is parsed and generated as expected. */ @Test public void testFullPath() { String streamName = "my-stream"; String moduleType = ModuleType.source.toString(); String moduleLabel = "my-label"; String moduleSequence = "0"; String container = UUID.randomUUID().toString(); String path = Paths.build( Paths.STREAM_DEPLOYMENTS, streamName, Paths.MODULES, String.format("%s.%s.%s.%s", moduleType, moduleLabel, moduleSequence, container)); StreamDeploymentsPath streamDeploymentsPath = new StreamDeploymentsPath(path); assertEquals(streamName, streamDeploymentsPath.getStreamName()); assertEquals(moduleType, streamDeploymentsPath.getModuleType()); assertEquals(moduleLabel, streamDeploymentsPath.getModuleLabel()); assertEquals(moduleSequence, streamDeploymentsPath.getModuleSequenceAsString()); assertEquals(container, streamDeploymentsPath.getContainer()); StreamDeploymentsPath streamDeploymentsPathEmptyCtor = new StreamDeploymentsPath() .setStreamName(streamName) .setModuleType(moduleType) .setModuleLabel(moduleLabel) .setModuleSequence(moduleSequence) .setContainer(container); assertEquals(path, streamDeploymentsPathEmptyCtor.build()); }
/** * Load the {@link org.springframework.xd.dirt.core.Stream} instance for a given stream name <i>if * the stream is deployed</i>. It will include the stream definition as well as any deployment * properties data for the stream deployment. * * @param client curator client * @param streamName the name of the stream to load * @param streamFactory stream factory used to create instance of stream * @return the stream instance, or {@code null} if the stream does not exist or is not deployed * @throws Exception if ZooKeeper access fails for any reason */ public static Stream loadStream( CuratorFramework client, String streamName, StreamFactory streamFactory) throws Exception { try { byte[] definition = client.getData().forPath(Paths.build(Paths.STREAMS, streamName)); Map<String, String> definitionMap = ZooKeeperUtils.bytesToMap(definition); byte[] deploymentPropertiesData = client.getData().forPath(Paths.build(Paths.STREAM_DEPLOYMENTS, streamName)); if (deploymentPropertiesData != null && deploymentPropertiesData.length > 0) { definitionMap.put("deploymentProperties", new String(deploymentPropertiesData, "UTF-8")); } return streamFactory.createStream(streamName, definitionMap); } catch (KeeperException.NoNodeException e) { // stream is not deployed or does not exist } return null; }
/** * Load the {@link org.springframework.xd.dirt.core.Job} instance for a given job name<i>if the * job is deployed</i>. * * @param client curator client * @param jobName the name of the job to load * @param jobFactory job factory used to create instance of job * @return the job instance, or {@code null} if the job does not exist or is not deployed * @throws Exception */ public static Job loadJob(CuratorFramework client, String jobName, JobFactory jobFactory) throws Exception { try { byte[] definition = client.getData().forPath(Paths.build(Paths.JOBS, jobName)); Map<String, String> definitionMap = ZooKeeperUtils.bytesToMap(definition); byte[] deploymentPropertiesData = client.getData().forPath(Paths.build(Paths.JOB_DEPLOYMENTS, jobName)); if (deploymentPropertiesData != null && deploymentPropertiesData.length > 0) { definitionMap.put("deploymentProperties", new String(deploymentPropertiesData, "UTF-8")); } return jobFactory.createJob(jobName, definitionMap); } catch (KeeperException.NoNodeException e) { // job is not deployed } return null; }
@Override public boolean exists(String id) { try { return (null != zkConnection.getClient().checkExists().forPath(Paths.build(Paths.STREAMS, id))); } catch (Exception e) { throw ZooKeeperUtils.wrapThrowable(e); } }
@Override public void delete(String id) { logger.trace("Deleting stream {}", id); String path = Paths.build(Paths.STREAMS, id); try { zkConnection.getClient().delete().deletingChildrenIfNeeded().forPath(path); } catch (Exception e) { // NoNodeException - nothing to delete ZooKeeperUtils.wrapAndThrowIgnoring(e, NoNodeException.class); } }
@Override public StreamDefinition findOne(String id) { try { byte[] bytes = zkConnection.getClient().getData().forPath(Paths.build(Paths.STREAMS, id)); if (bytes == null) { return null; } Map<String, String> map = ZooKeeperUtils.bytesToMap(bytes); StreamDefinition streamDefinition = new StreamDefinition(id, map.get(DEFINITION_KEY)); if (map.get(MODULE_DEFINITIONS_KEY) != null) { List<ModuleDefinition> moduleDefinitions = objectReader.readValue(map.get(MODULE_DEFINITIONS_KEY)); streamDefinition.setModuleDefinitions(moduleDefinitions); } return streamDefinition; } catch (Exception e) { // NoNodeException - the definition does not exist ZooKeeperUtils.wrapAndThrowIgnoring(e, NoNodeException.class); } return null; }
/** * Provides basic deployment behavior, whereby running state of deployed definitions is not * persisted. * * @return the definition object for the given name * @throws NoSuchDefinitionException if there is no definition by the given name */ protected D basicDeploy(String name, Map<String, String> properties) { Assert.hasText(name, "name cannot be blank or null"); logger.trace("Deploying {}", name); final D definition = getDefinitionRepository().findOne(name); if (definition == null) { throwNoSuchDefinitionException(name); } validateDeploymentProperties(definition, properties); try { String deploymentPath = getDeploymentPath(definition); String statusPath = Paths.build(deploymentPath, Paths.STATUS); byte[] propertyBytes = DeploymentPropertiesFormat.formatDeploymentProperties(properties).getBytes("UTF-8"); byte[] statusBytes = ZooKeeperUtils.mapToBytes( new DeploymentUnitStatus(DeploymentUnitStatus.State.deploying).toMap()); zkConnection .getClient() .inTransaction() .create() .forPath(deploymentPath, propertyBytes) .and() .create() .withMode(CreateMode.EPHEMERAL) .forPath(statusPath, statusBytes) .and() .commit(); } catch (KeeperException.NodeExistsException e) { throwAlreadyDeployedException(name); } catch (Exception e) { throw ZooKeeperUtils.wrapThrowable(e); } return definition; }
/** {@inheritDoc} */ @Override protected String getDeploymentPath(StreamDefinition definition) { return Paths.build(Paths.STREAM_DEPLOYMENTS, definition.getName()); }