You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@curator.apache.org by ti...@apache.org on 2022/06/26 12:34:48 UTC
[curator] branch master updated: CURATOR-643: Add option to disable parent creation for PersistentTtlNode (#422)
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 <pa...@gmail.com>
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
{