This is an automated email from the ASF dual-hosted git repository.
tison pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/curator.git
The following commit(s) were added to refs/heads/master by this push:
new f4abf511 CURATOR-643: Add option to disable parent creation for
PersistentTtlNode (#422)
f4abf511 is described below
commit f4abf511c6fc514aae41ed75deb2483bf9726f24
Author: Paul Boutes <[email protected]>
AuthorDate: Sun Jun 26 14:34:41 2022 +0200
CURATOR-643: Add option to disable parent creation for PersistentTtlNode
(#422)
The PR enables the `PersistentTtlNode` to configure `useParentCreation`
boolean flag, which is by default set as `true`.
---
.../framework/recipes/nodes/PersistentTtlNode.java | 19 ++++++++--
.../recipes/nodes/TestPersistentTtlNode.java | 41 ++++++++++++++++++++++
2 files changed, 57 insertions(+), 3 deletions(-)
diff --git
a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/nodes/PersistentTtlNode.java
b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/nodes/PersistentTtlNode.java
index 91f5f714..9f019d6e 100644
---
a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/nodes/PersistentTtlNode.java
+++
b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/nodes/PersistentTtlNode.java
@@ -76,7 +76,19 @@ public class PersistentTtlNode implements Closeable
*/
public PersistentTtlNode(CuratorFramework client, String path, long ttlMs,
byte[] initData)
{
- this(client,
Executors.newSingleThreadScheduledExecutor(ThreadUtils.newThreadFactory("PersistentTtlNode")),
path, ttlMs, initData, DEFAULT_CHILD_NODE_NAME, DEFAULT_TOUCH_SCHEDULE_FACTOR);
+ this(client,
Executors.newSingleThreadScheduledExecutor(ThreadUtils.newThreadFactory("PersistentTtlNode")),
path, ttlMs, initData, DEFAULT_CHILD_NODE_NAME, DEFAULT_TOUCH_SCHEDULE_FACTOR,
true);
+ }
+
+ /**
+ * @param client the client
+ * @param path path for the parent ZNode
+ * @param ttlMs max ttl for the node in milliseconds
+ * @param initData data for the node
+ * @param useParentCreation if true, parent ZNode can be created without
ancestors
+ */
+ public PersistentTtlNode(CuratorFramework client, String path, long ttlMs,
byte[] initData, boolean useParentCreation)
+ {
+ this(client,
Executors.newSingleThreadScheduledExecutor(ThreadUtils.newThreadFactory("PersistentTtlNode")),
path, ttlMs, initData, DEFAULT_CHILD_NODE_NAME, DEFAULT_TOUCH_SCHEDULE_FACTOR,
useParentCreation);
}
/**
@@ -88,13 +100,14 @@ public class PersistentTtlNode implements Closeable
* @param childNodeName name to use for the child node of the node created
at <code>path</code>
* @param touchScheduleFactor how ofter to set/create the child node as a
factor of the ttlMs. i.e.
* the child is touched every <code>(ttlMs /
touchScheduleFactor)</code>
+ * @param useParentCreation if true, parent ZNode can be created without
ancestors
*/
- public PersistentTtlNode(CuratorFramework client, ScheduledExecutorService
executorService, String path, long ttlMs, byte[] initData, String
childNodeName, int touchScheduleFactor)
+ public PersistentTtlNode(CuratorFramework client, ScheduledExecutorService
executorService, String path, long ttlMs, byte[] initData, String
childNodeName, int touchScheduleFactor, boolean useParentCreation)
{
this.client = Objects.requireNonNull(client, "client cannot be null");
this.ttlMs = ttlMs;
this.touchScheduleFactor = touchScheduleFactor;
- node = new PersistentNode(client, CreateMode.CONTAINER, false, path,
initData)
+ node = new PersistentNode(client, CreateMode.CONTAINER, false, path,
initData, useParentCreation)
{
@Override
protected void deleteNode()
diff --git
a/curator-recipes/src/test/java/org/apache/curator/framework/recipes/nodes/TestPersistentTtlNode.java
b/curator-recipes/src/test/java/org/apache/curator/framework/recipes/nodes/TestPersistentTtlNode.java
index 040bb055..96d51383 100644
---
a/curator-recipes/src/test/java/org/apache/curator/framework/recipes/nodes/TestPersistentTtlNode.java
+++
b/curator-recipes/src/test/java/org/apache/curator/framework/recipes/nodes/TestPersistentTtlNode.java
@@ -22,6 +22,8 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
@@ -31,6 +33,7 @@ import
org.apache.curator.framework.recipes.cache.PathChildrenCacheListener;
import org.apache.curator.retry.RetryOneTime;
import org.apache.curator.test.Timing;
import org.apache.curator.test.compatibility.CuratorTestBase;
+import org.apache.curator.test.compatibility.Timing2;
import org.apache.curator.utils.ZKPaths;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
@@ -117,6 +120,44 @@ public class TestPersistentTtlNode extends CuratorTestBase
}
}
+ @Test
+ public void testRecreationOfParentNodeWithParentCreationOff() throws
Exception
+ {
+ final byte[] TEST_DATA = "hey".getBytes();
+ Timing2 timing = new Timing2();
+ String containerPath = ZKPaths.makePath("test", "one", "two");
+ String childPath = ZKPaths.makePath("test", "one", "two",
PersistentTtlNode.DEFAULT_CHILD_NODE_NAME);
+
+ try (CuratorFramework client =
CuratorFrameworkFactory.newClient(server.getConnectString(), timing.session(),
timing.connection(), new RetryOneTime(1)))
+ {
+ client.start();
+ client.create().creatingParentsIfNeeded().forPath("/test/one");
+
+ try (PersistentTtlNode node = new PersistentTtlNode(client,
containerPath, ttlMs, TEST_DATA, false))
+ {
+ node.start();
+ assertTrue(node.waitForInitialCreate(timing.milliseconds(),
TimeUnit.MILLISECONDS));
+
+ Thread.sleep(ttlMs + (ttlMs / 2));
+ assertNotNull(client.checkExists().forPath(containerPath));
+ assertNotNull(client.checkExists().forPath(childPath));
+
+
+
client.delete().deletingChildrenIfNeeded().forPath("/test/one");
+ timing.sleepABit();
+
+ // The underlying persistent node should not be able to
recreate itself as the lazy parent creation is disabled
+ assertNull(client.checkExists().forPath(containerPath));
+ assertNull(client.checkExists().forPath(childPath));
+
+ assertThrows(IllegalStateException.class, () ->
node.setData(new byte[0]));
+
+ // The underlying persistent node data should still be the
initial one
+ assertArrayEquals(TEST_DATA, node.getData());
+ }
+ }
+ }
+
@Test
public void testEventsOnParent() throws Exception
{