You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@helix.apache.org by hu...@apache.org on 2022/05/20 14:08:08 UTC

[helix] branch zookeeper-api-ttlcontainer updated: Add TTL and Container modes to RealmAwareZkClient and its implementations (#2103)

This is an automated email from the ASF dual-hosted git repository.

hulee pushed a commit to branch zookeeper-api-ttlcontainer
in repository https://gitbox.apache.org/repos/asf/helix.git


The following commit(s) were added to refs/heads/zookeeper-api-ttlcontainer by this push:
     new a08b8dad7 Add TTL and Container modes to RealmAwareZkClient and its implementations (#2103)
a08b8dad7 is described below

commit a08b8dad72fc163575f9e0211ca9d4b59035d3b2
Author: Ramin Bashizade <ra...@linkedin.com>
AuthorDate: Fri May 20 07:08:02 2022 -0700

    Add TTL and Container modes to RealmAwareZkClient and its implementations (#2103)
    
    New API methods were added to ZkClient in https://github.com/apache/helix/pull/2082 and https://github.com/apache/helix/pull/2090 to support creation of ZNodes in TTL and Container modes. This PR builds on those API to add this support to RealmAwareZkClient and its implementations.
---
 .../zookeeper/api/client/RealmAwareZkClient.java   | 32 ++++++++
 .../zookeeper/impl/client/DedicatedZkClient.java   | 80 +++++++++++++++++++
 .../zookeeper/impl/client/FederatedZkClient.java   | 83 +++++++++++++++++++-
 .../zookeeper/impl/client/SharedZkClient.java      | 90 +++++++++++++++++++++-
 .../impl/factory/SharedZkClientFactory.java        |  7 +-
 .../client/RealmAwareZkClientFactoryTestBase.java  | 67 +++++++++++++++-
 .../impl/client/TestFederatedZkClient.java         | 79 ++++++++++++++++++-
 7 files changed, 426 insertions(+), 12 deletions(-)

diff --git a/zookeeper-api/src/main/java/org/apache/helix/zookeeper/api/client/RealmAwareZkClient.java b/zookeeper-api/src/main/java/org/apache/helix/zookeeper/api/client/RealmAwareZkClient.java
index d00642039..99874c7eb 100644
--- a/zookeeper-api/src/main/java/org/apache/helix/zookeeper/api/client/RealmAwareZkClient.java
+++ b/zookeeper-api/src/main/java/org/apache/helix/zookeeper/api/client/RealmAwareZkClient.java
@@ -175,10 +175,34 @@ public interface RealmAwareZkClient {
 
   void createPersistent(String path, Object data, List<ACL> acl);
 
+  void createPersistentWithTTL(String path, long ttl);
+
+  void createPersistentWithTTL(String path, boolean createParents, long ttl);
+
+  void createPersistentWithTTL(String path, boolean createParents, List<ACL> acl, long ttl);
+
+  void createPersistentWithTTL(String path, Object data, long ttl);
+
+  void createPersistentWithTTL(String path, Object data, List<ACL> acl, long ttl);
+
   String createPersistentSequential(String path, Object data);
 
   String createPersistentSequential(String path, Object data, List<ACL> acl);
 
+  String createPersistentSequentialWithTTL(String path, Object data, long ttl);
+
+  String createPersistentSequentialWithTTL(String path, Object data, List<ACL> acl, long ttl);
+
+  void createContainer(String path);
+
+  void createContainer(String path, boolean createParents);
+
+  void createContainer(String path, boolean createParents, List<ACL> acl);
+
+  void createContainer(String path, Object data);
+
+  void createContainer(String path, Object data, List<ACL> acl);
+
   void createEphemeral(final String path);
 
   void createEphemeral(final String path, final String sessionId);
@@ -189,8 +213,13 @@ public interface RealmAwareZkClient {
 
   String create(final String path, Object data, final CreateMode mode);
 
+  String create(final String path, Object data, final CreateMode mode, long ttl);
+
   String create(final String path, Object datat, final List<ACL> acl, final CreateMode mode);
 
+  String create(final String path, Object datat, final List<ACL> acl, final CreateMode mode,
+      long ttl);
+
   void createEphemeral(final String path, final Object data);
 
   void createEphemeral(final String path, final Object data, final String sessionId);
@@ -246,6 +275,9 @@ public interface RealmAwareZkClient {
   void asyncCreate(final String path, Object datat, final CreateMode mode,
       final ZkAsyncCallbacks.CreateCallbackHandler cb);
 
+  void asyncCreate(final String path, Object datat, final CreateMode mode, long ttl,
+      final ZkAsyncCallbacks.CreateCallbackHandler cb);
+
   void asyncSetData(final String path, Object datat, final int version,
       final ZkAsyncCallbacks.SetDataCallbackHandler cb);
 
diff --git a/zookeeper-api/src/main/java/org/apache/helix/zookeeper/impl/client/DedicatedZkClient.java b/zookeeper-api/src/main/java/org/apache/helix/zookeeper/impl/client/DedicatedZkClient.java
index 74ff0adf3..738a070b4 100644
--- a/zookeeper-api/src/main/java/org/apache/helix/zookeeper/impl/client/DedicatedZkClient.java
+++ b/zookeeper-api/src/main/java/org/apache/helix/zookeeper/impl/client/DedicatedZkClient.java
@@ -181,6 +181,32 @@ public class DedicatedZkClient implements RealmAwareZkClient {
     create(path, data, acl, CreateMode.PERSISTENT);
   }
 
+  @Override
+  public void createPersistentWithTTL(String path, long ttl) {
+    createPersistentWithTTL(path, false, ttl);
+  }
+
+  @Override
+  public void createPersistentWithTTL(String path, boolean createParents, long ttl) {
+    createPersistentWithTTL(path, createParents, ZooDefs.Ids.OPEN_ACL_UNSAFE, ttl);
+  }
+
+  @Override
+  public void createPersistentWithTTL(String path, boolean createParents, List<ACL> acl, long ttl) {
+    checkIfPathContainsShardingKey(path);
+    _rawZkClient.createPersistentWithTTL(path, createParents, acl, ttl);
+  }
+
+  @Override
+  public void createPersistentWithTTL(String path, Object data, long ttl) {
+    create(path, data, CreateMode.PERSISTENT_WITH_TTL, ttl);
+  }
+
+  @Override
+  public void createPersistentWithTTL(String path, Object data, List<ACL> acl, long ttl) {
+    create(path, data, acl, CreateMode.PERSISTENT_WITH_TTL, ttl);
+  }
+
   @Override
   public String createPersistentSequential(String path, Object data) {
     return create(path, data, CreateMode.PERSISTENT_SEQUENTIAL);
@@ -191,6 +217,42 @@ public class DedicatedZkClient implements RealmAwareZkClient {
     return create(path, data, acl, CreateMode.PERSISTENT_SEQUENTIAL);
   }
 
+  @Override
+  public String createPersistentSequentialWithTTL(String path, Object data, long ttl) {
+    return create(path, data, CreateMode.PERSISTENT_SEQUENTIAL_WITH_TTL, ttl);
+  }
+
+  @Override
+  public String createPersistentSequentialWithTTL(String path, Object data, List<ACL> acl, long ttl) {
+    return create(path, data, acl, CreateMode.PERSISTENT_SEQUENTIAL_WITH_TTL, ttl);
+  }
+
+  @Override
+  public void createContainer(String path) {
+    createContainer(path, false);
+  }
+
+  @Override
+  public void createContainer(String path, boolean createParents) {
+    createContainer(path, createParents, ZooDefs.Ids.OPEN_ACL_UNSAFE);
+  }
+
+  @Override
+  public void createContainer(String path, boolean createParents, List<ACL> acl) {
+    checkIfPathContainsShardingKey(path);
+    _rawZkClient.createContainer(path, createParents, acl);
+  }
+
+  @Override
+  public void createContainer(String path, Object data) {
+    create(path, data, CreateMode.CONTAINER);
+  }
+
+  @Override
+  public void createContainer(String path, Object data, List<ACL> acl) {
+    create(path, data, acl, CreateMode.CONTAINER);
+  }
+
   @Override
   public void createEphemeral(String path) {
     create(path, null, CreateMode.EPHEMERAL);
@@ -217,12 +279,23 @@ public class DedicatedZkClient implements RealmAwareZkClient {
     return create(path, data, ZooDefs.Ids.OPEN_ACL_UNSAFE, mode);
   }
 
+  @Override
+  public String create(String path, Object data, CreateMode mode, long ttl) {
+    return create(path, data, ZooDefs.Ids.OPEN_ACL_UNSAFE, mode, ttl);
+  }
+
   @Override
   public String create(String path, Object datat, List<ACL> acl, CreateMode mode) {
     checkIfPathContainsShardingKey(path);
     return _rawZkClient.create(path, datat, acl, mode);
   }
 
+  @Override
+  public String create(String path, Object datat, List<ACL> acl, CreateMode mode, long ttl) {
+    checkIfPathContainsShardingKey(path);
+    return _rawZkClient.create(path, datat, acl, mode, ttl);
+  }
+
   @Override
   public void createEphemeral(String path, Object data) {
     create(path, data, CreateMode.EPHEMERAL);
@@ -366,6 +439,13 @@ public class DedicatedZkClient implements RealmAwareZkClient {
     return writeDataReturnStat(path, datat, expectedVersion);
   }
 
+  @Override
+  public void asyncCreate(String path, Object datat, CreateMode mode, long ttl,
+      ZkAsyncCallbacks.CreateCallbackHandler cb) {
+    checkIfPathContainsShardingKey(path);
+    _rawZkClient.asyncCreate(path, datat, mode, ttl, cb);
+  }
+
   @Override
   public void asyncCreate(String path, Object datat, CreateMode mode,
       ZkAsyncCallbacks.CreateCallbackHandler cb) {
diff --git a/zookeeper-api/src/main/java/org/apache/helix/zookeeper/impl/client/FederatedZkClient.java b/zookeeper-api/src/main/java/org/apache/helix/zookeeper/impl/client/FederatedZkClient.java
index dc55d532e..51a22c728 100644
--- a/zookeeper-api/src/main/java/org/apache/helix/zookeeper/impl/client/FederatedZkClient.java
+++ b/zookeeper-api/src/main/java/org/apache/helix/zookeeper/impl/client/FederatedZkClient.java
@@ -191,6 +191,31 @@ public class FederatedZkClient implements RealmAwareZkClient {
     create(path, data, acl, CreateMode.PERSISTENT);
   }
 
+  @Override
+  public void createPersistentWithTTL(String path, long ttl) {
+    createPersistentWithTTL(path, false, ttl);
+  }
+
+  @Override
+  public void createPersistentWithTTL(String path, boolean createParents, long ttl) {
+    createPersistentWithTTL(path, createParents, ZooDefs.Ids.OPEN_ACL_UNSAFE, ttl);
+  }
+
+  @Override
+  public void createPersistentWithTTL(String path, boolean createParents, List<ACL> acl, long ttl) {
+    getZkClient(path).createPersistentWithTTL(path, createParents, acl, ttl);
+  }
+
+  @Override
+  public void createPersistentWithTTL(String path, Object data, long ttl) {
+    create(path, data, CreateMode.PERSISTENT_WITH_TTL, ttl);
+  }
+
+  @Override
+  public void createPersistentWithTTL(String path, Object data, List<ACL> acl, long ttl) {
+    create(path, data, acl, CreateMode.PERSISTENT_WITH_TTL, ttl);
+  }
+
   @Override
   public String createPersistentSequential(String path, Object data) {
     return create(path, data, CreateMode.PERSISTENT_SEQUENTIAL);
@@ -201,6 +226,41 @@ public class FederatedZkClient implements RealmAwareZkClient {
     return create(path, data, acl, CreateMode.PERSISTENT_SEQUENTIAL);
   }
 
+  @Override
+  public String createPersistentSequentialWithTTL(String path, Object data, long ttl) {
+    return create(path, data, CreateMode.PERSISTENT_SEQUENTIAL_WITH_TTL, ttl);
+  }
+
+  @Override
+  public String createPersistentSequentialWithTTL(String path, Object data, List<ACL> acl, long ttl) {
+    return create(path, data, acl, CreateMode.PERSISTENT_SEQUENTIAL_WITH_TTL, ttl);
+  }
+
+  @Override
+  public void createContainer(String path) {
+    createContainer(path, false);
+  }
+
+  @Override
+  public void createContainer(String path, boolean createParents) {
+    createContainer(path, createParents, ZooDefs.Ids.OPEN_ACL_UNSAFE);
+  }
+
+  @Override
+  public void createContainer(String path, boolean createParents, List<ACL> acl) {
+    getZkClient(path).createContainer(path, createParents, acl);
+  }
+
+  @Override
+  public void createContainer(String path, Object data) {
+    create(path, data, CreateMode.CONTAINER);
+  }
+
+  @Override
+  public void createContainer(String path, Object data, List<ACL> acl) {
+    create(path, data, acl, CreateMode.CONTAINER);
+  }
+
   @Override
   public void createEphemeral(String path) {
     create(path, null, CreateMode.EPHEMERAL);
@@ -226,11 +286,21 @@ public class FederatedZkClient implements RealmAwareZkClient {
     return create(path, data, ZooDefs.Ids.OPEN_ACL_UNSAFE, mode);
   }
 
+  @Override
+  public String create(String path, Object data, CreateMode mode, long ttl) {
+    return create(path, data, ZooDefs.Ids.OPEN_ACL_UNSAFE, mode, ttl);
+  }
+
   @Override
   public String create(String path, Object data, List<ACL> acl, CreateMode mode) {
     return create(path, data, acl, mode, null);
   }
 
+  @Override
+  public String create(String path, Object data, List<ACL> acl, CreateMode mode, long ttl) {
+    return create(path, data, acl, mode, ttl, null);
+  }
+
   @Override
   public void createEphemeral(String path, Object data) {
     create(path, data, CreateMode.EPHEMERAL);
@@ -359,6 +429,12 @@ public class FederatedZkClient implements RealmAwareZkClient {
     return writeDataReturnStat(path, data, expectedVersion);
   }
 
+  @Override
+  public void asyncCreate(String path, Object data, CreateMode mode, long ttl,
+      ZkAsyncCallbacks.CreateCallbackHandler cb) {
+    getZkClient(path).asyncCreate(path, data, mode, ttl, cb);
+  }
+
   @Override
   public void asyncCreate(String path, Object data, CreateMode mode,
       ZkAsyncCallbacks.CreateCallbackHandler cb) {
@@ -501,13 +577,18 @@ public class FederatedZkClient implements RealmAwareZkClient {
 
   private String create(final String path, final Object dataObject, final List<ACL> acl,
       final CreateMode mode, final String expectedSessionId) {
+    return create(path, dataObject, acl, mode, ZkClient.TTL_NOT_SET, expectedSessionId);
+  }
+
+  private String create(final String path, final Object dataObject, final List<ACL> acl,
+      final CreateMode mode, final long ttl, final String expectedSessionId) {
     if (mode.isEphemeral()) {
       throwUnsupportedOperationException();
     }
 
     // Create mode is not session-aware, so the node does not have to be created
     // by the expectedSessionId.
-    return getZkClient(path).create(path, dataObject, acl, mode);
+    return getZkClient(path).create(path, dataObject, acl, mode, ttl);
   }
 
   private ZkClient getZkClient(String path) {
diff --git a/zookeeper-api/src/main/java/org/apache/helix/zookeeper/impl/client/SharedZkClient.java b/zookeeper-api/src/main/java/org/apache/helix/zookeeper/impl/client/SharedZkClient.java
index 7f529d20a..093538fa6 100644
--- a/zookeeper-api/src/main/java/org/apache/helix/zookeeper/impl/client/SharedZkClient.java
+++ b/zookeeper-api/src/main/java/org/apache/helix/zookeeper/impl/client/SharedZkClient.java
@@ -39,6 +39,7 @@ import org.apache.helix.zookeeper.zkclient.serialize.ZkSerializer;
 import org.apache.zookeeper.CreateMode;
 import org.apache.zookeeper.Op;
 import org.apache.zookeeper.OpResult;
+import org.apache.zookeeper.ZooDefs;
 import org.apache.zookeeper.data.ACL;
 import org.apache.zookeeper.data.Stat;
 import org.slf4j.Logger;
@@ -189,6 +190,33 @@ public class SharedZkClient implements RealmAwareZkClient {
     _innerSharedZkClient.createPersistent(path, data, acl);
   }
 
+  @Override
+  public void createPersistentWithTTL(String path, long ttl) {
+    createPersistentWithTTL(path, false, ttl);
+  }
+
+  @Override
+  public void createPersistentWithTTL(String path, boolean createParents, long ttl) {
+    createPersistentWithTTL(path, createParents, ZooDefs.Ids.OPEN_ACL_UNSAFE, ttl);
+  }
+
+  @Override
+  public void createPersistentWithTTL(String path, boolean createParents, List<ACL> acl, long ttl) {
+    checkIfPathContainsShardingKey(path);
+    _innerSharedZkClient.createPersistentWithTTL(path, createParents, acl, ttl);
+  }
+
+  @Override
+  public void createPersistentWithTTL(String path, Object data, long ttl) {
+    createPersistentWithTTL(path, data, ZooDefs.Ids.OPEN_ACL_UNSAFE, ttl);
+  }
+
+  @Override
+  public void createPersistentWithTTL(String path, Object data, List<ACL> acl, long ttl) {
+    checkIfPathContainsShardingKey(path);
+    _innerSharedZkClient.createPersistentWithTTL(path, data, acl, ttl);
+  }
+
   @Override
   public String createPersistentSequential(String path, Object data) {
     checkIfPathContainsShardingKey(path);
@@ -201,6 +229,44 @@ public class SharedZkClient implements RealmAwareZkClient {
     return _innerSharedZkClient.createPersistentSequential(path, data, acl);
   }
 
+  @Override
+  public String createPersistentSequentialWithTTL(String path, Object data, long ttl) {
+    return createPersistentSequentialWithTTL(path, data, ZooDefs.Ids.OPEN_ACL_UNSAFE, ttl);
+  }
+
+  @Override
+  public String createPersistentSequentialWithTTL(String path, Object data, List<ACL> acl, long ttl) {
+    checkIfPathContainsShardingKey(path);
+    return _innerSharedZkClient.createPersistentSequentialWithTTL(path, data, acl, ttl);
+  }
+
+  @Override
+  public void createContainer(String path) {
+    createContainer(path, false);
+  }
+
+  @Override
+  public void createContainer(String path, boolean createParents) {
+    createContainer(path, createParents, ZooDefs.Ids.OPEN_ACL_UNSAFE);
+  }
+
+  @Override
+  public void createContainer(String path, boolean createParents, List<ACL> acl) {
+    checkIfPathContainsShardingKey(path);
+    _innerSharedZkClient.createContainer(path, createParents, acl);
+  }
+
+  @Override
+  public void createContainer(String path, Object data) {
+    createContainer(path, data, ZooDefs.Ids.OPEN_ACL_UNSAFE);
+  }
+
+  @Override
+  public void createContainer(String path, Object data, List<ACL> acl) {
+    checkIfPathContainsShardingKey(path);
+    _innerSharedZkClient.createContainer(path, data, acl);
+  }
+
   @Override
   public void createEphemeral(String path) {
     throw new UnsupportedOperationException(
@@ -231,16 +297,26 @@ public class SharedZkClient implements RealmAwareZkClient {
 
   @Override
   public String create(String path, Object data, CreateMode mode) {
+    return create(path, data, mode, ZkClient.TTL_NOT_SET);
+  }
+
+  @Override
+  public String create(String path, Object data, CreateMode mode, long ttl) {
     checkIfPathContainsShardingKey(path);
     // delegate to _innerSharedZkClient is fine as _innerSharedZkClient would not allow creating ephemeral node.
     // this still keeps the same behavior.
-    return _innerSharedZkClient.create(path, data, mode);
+    return _innerSharedZkClient.create(path, data, mode, ttl);
   }
 
   @Override
   public String create(String path, Object datat, List<ACL> acl, CreateMode mode) {
+    return create(path, datat, acl, mode, ZkClient.TTL_NOT_SET);
+  }
+
+  @Override
+  public String create(String path, Object datat, List<ACL> acl, CreateMode mode, long ttl) {
     checkIfPathContainsShardingKey(path);
-    return _innerSharedZkClient.create(path, datat, acl, mode);
+    return _innerSharedZkClient.create(path, datat, acl, mode, ttl);
   }
 
   @Override
@@ -403,10 +479,16 @@ public class SharedZkClient implements RealmAwareZkClient {
   }
 
   @Override
-  public void asyncCreate(String path, Object datat, CreateMode mode,
+  public void asyncCreate(String path, Object datat, CreateMode mode, long ttl,
       ZkAsyncCallbacks.CreateCallbackHandler cb) {
     checkIfPathContainsShardingKey(path);
-    _innerSharedZkClient.asyncCreate(path, datat, mode, cb);
+    _innerSharedZkClient.asyncCreate(path, datat, mode, ttl, cb);
+  }
+
+  @Override
+  public void asyncCreate(String path, Object datat, CreateMode mode,
+      ZkAsyncCallbacks.CreateCallbackHandler cb) {
+    asyncCreate(path, datat, mode, ZkClient.TTL_NOT_SET, cb);
   }
 
   @Override
diff --git a/zookeeper-api/src/main/java/org/apache/helix/zookeeper/impl/factory/SharedZkClientFactory.java b/zookeeper-api/src/main/java/org/apache/helix/zookeeper/impl/factory/SharedZkClientFactory.java
index e3cbf5d31..48d1bdee9 100644
--- a/zookeeper-api/src/main/java/org/apache/helix/zookeeper/impl/factory/SharedZkClientFactory.java
+++ b/zookeeper-api/src/main/java/org/apache/helix/zookeeper/impl/factory/SharedZkClientFactory.java
@@ -194,12 +194,17 @@ public class SharedZkClientFactory extends HelixZkClientFactory {
     @Override
     public String create(final String path, Object datat, final List<ACL> acl,
         final CreateMode mode) {
+      return create(path, datat, acl, mode, TTL_NOT_SET);
+    }
+    @Override
+    public String create(final String path, Object datat, final List<ACL> acl,
+        final CreateMode mode, long ttl) {
       if (mode.isEphemeral()) {
         throw new UnsupportedOperationException(
             "Create ephemeral nodes using " + SharedZkClient.class.getSimpleName()
                 + " is not supported.");
       }
-      return super.create(path, datat, acl, mode);
+      return super.create(path, datat, acl, mode, ttl);
     }
 
     @Override
diff --git a/zookeeper-api/src/test/java/org/apache/helix/zookeeper/impl/client/RealmAwareZkClientFactoryTestBase.java b/zookeeper-api/src/test/java/org/apache/helix/zookeeper/impl/client/RealmAwareZkClientFactoryTestBase.java
index 6c3555f4b..a374b1f0e 100644
--- a/zookeeper-api/src/test/java/org/apache/helix/zookeeper/impl/client/RealmAwareZkClientFactoryTestBase.java
+++ b/zookeeper-api/src/test/java/org/apache/helix/zookeeper/impl/client/RealmAwareZkClientFactoryTestBase.java
@@ -113,15 +113,76 @@ public abstract class RealmAwareZkClientFactoryTestBase extends RealmAwareZkClie
     }
   }
 
+  /**
+   * Test creating a container node.
+   */
+  @Test(dependsOnMethods = "testRealmAwareZkClientCreation")
+  public void testRealmAwareZkClientCreateContainer() {
+    System.setProperty("zookeeper.extendedTypesEnabled", "true");
+    _realmAwareZkClient.setZkSerializer(new ZNRecordSerializer());
+
+    // Test with createParents = true
+    _realmAwareZkClient.createContainer(TEST_VALID_PATH, true);
+    Assert.assertTrue(_realmAwareZkClient.exists(TEST_VALID_PATH));
+
+    // Test writing and reading data
+    String childPath = TEST_VALID_PATH + "/child";
+    _realmAwareZkClient.createContainer(childPath, DUMMY_RECORD);
+    ZNRecord retrievedRecord = _realmAwareZkClient.readData(childPath);
+    Assert.assertEquals(DUMMY_RECORD.getSimpleField("Dummy"),
+        retrievedRecord.getSimpleField("Dummy"));
+
+    // Clean up
+    _realmAwareZkClient.deleteRecursively(TEST_VALID_PATH);
+  }
+
+  /**
+   * Test creating a sequential TTL node.
+   */
+  @Test(dependsOnMethods = "testRealmAwareZkClientCreateContainer")
+  public void testRealmAwareZkClientCreateSequentialWithTTL() {
+    // Test writing and reading data
+    _realmAwareZkClient.createPersistent(TEST_VALID_PATH, true);
+    long ttl = 1L;
+    String childPath = TEST_VALID_PATH + "/child";
+    _realmAwareZkClient.createPersistentSequentialWithTTL(childPath, DUMMY_RECORD, ttl);
+    ZNRecord retrievedRecord = _realmAwareZkClient.readData(childPath + "0000000000");
+    Assert.assertEquals(DUMMY_RECORD.getSimpleField("Dummy"),
+        retrievedRecord.getSimpleField("Dummy"));
+
+    // Clean up
+    _realmAwareZkClient.deleteRecursively(TEST_VALID_PATH);
+  }
+
+  /**
+   * Test creating a TTL node.
+   */
+  @Test(dependsOnMethods = "testRealmAwareZkClientCreateSequentialWithTTL")
+  public void testRealmAwareZkClientCreateWithTTL() {
+    // Test with createParents = true
+    long ttl = 1L;
+    _realmAwareZkClient.createPersistentWithTTL(TEST_VALID_PATH, true, ttl);
+    Assert.assertTrue(_realmAwareZkClient.exists(TEST_VALID_PATH));
+
+    // Test writing and reading data
+    String childPath = TEST_VALID_PATH + "/child";
+    _realmAwareZkClient.createPersistentWithTTL(childPath, DUMMY_RECORD, ttl);
+    ZNRecord retrievedRecord = _realmAwareZkClient.readData(childPath);
+    Assert.assertEquals(DUMMY_RECORD.getSimpleField("Dummy"),
+        retrievedRecord.getSimpleField("Dummy"));
+
+    // Clean up
+    _realmAwareZkClient.deleteRecursively(TEST_VALID_PATH);
+    System.clearProperty("zookeeper.extendedTypesEnabled");
+  }
+
   /**
    * Test the persistent create() call against a valid path and an invalid path.
    * Valid path is one that belongs to the realm designated by the sharding key.
    * Invalid path is one that does not belong to the realm designated by the sharding key.
    */
-  @Test(dependsOnMethods = "testRealmAwareZkClientCreation")
+  @Test(dependsOnMethods = "testRealmAwareZkClientCreateWithTTL")
   public void testRealmAwareZkClientCreatePersistent() {
-    _realmAwareZkClient.setZkSerializer(new ZNRecordSerializer());
-
     // Test writing and reading against the validPath
     _realmAwareZkClient.createPersistent(TEST_VALID_PATH, true);
     _realmAwareZkClient.writeData(TEST_VALID_PATH, DUMMY_RECORD);
diff --git a/zookeeper-api/src/test/java/org/apache/helix/zookeeper/impl/client/TestFederatedZkClient.java b/zookeeper-api/src/test/java/org/apache/helix/zookeeper/impl/client/TestFederatedZkClient.java
index e201905d4..f73624c2a 100644
--- a/zookeeper-api/src/test/java/org/apache/helix/zookeeper/impl/client/TestFederatedZkClient.java
+++ b/zookeeper-api/src/test/java/org/apache/helix/zookeeper/impl/client/TestFederatedZkClient.java
@@ -167,15 +167,88 @@ public class TestFederatedZkClient extends RealmAwareZkClientTestBase {
     }
   }
 
+  /**
+   * Test creating a container node.
+   */
+  @Test(dependsOnMethods = "testUnsupportedOperations")
+  public void testRealmAwareZkClientCreateContainer() {
+    System.setProperty("zookeeper.extendedTypesEnabled", "true");
+    _realmAwareZkClient.setZkSerializer(new ZNRecordSerializer());
+
+    // Create a dummy ZNRecord
+    ZNRecord znRecord = new ZNRecord("DummyRecord");
+    znRecord.setSimpleField("Dummy", "Value");
+
+    // Test with createParents = true
+    _realmAwareZkClient.createContainer(TEST_VALID_PATH, true);
+    Assert.assertTrue(_realmAwareZkClient.exists(TEST_VALID_PATH));
+
+    // Test writing and reading data
+    String childPath = TEST_VALID_PATH + "/child";
+    _realmAwareZkClient.createContainer(childPath, znRecord);
+    ZNRecord retrievedRecord = _realmAwareZkClient.readData(childPath);
+    Assert.assertEquals(znRecord.getSimpleField("Dummy"),
+        retrievedRecord.getSimpleField("Dummy"));
+
+    // Clean up
+    _realmAwareZkClient.deleteRecursively(TEST_VALID_PATH);
+  }
+
+  /**
+   * Test creating a sequential TTL node.
+   */
+  @Test(dependsOnMethods = "testRealmAwareZkClientCreateContainer")
+  public void testRealmAwareZkClientCreateSequentialWithTTL() {
+    // Create a dummy ZNRecord
+    ZNRecord znRecord = new ZNRecord("DummyRecord");
+    znRecord.setSimpleField("Dummy", "Value");
+
+    // Test writing and reading data
+    _realmAwareZkClient.createPersistent(TEST_VALID_PATH, true);
+    long ttl = 1L;
+    String childPath = TEST_VALID_PATH + "/child";
+    _realmAwareZkClient.createPersistentSequentialWithTTL(childPath, znRecord, ttl);
+    ZNRecord retrievedRecord = _realmAwareZkClient.readData(childPath + "0000000000");
+    Assert.assertEquals(znRecord.getSimpleField("Dummy"),
+        retrievedRecord.getSimpleField("Dummy"));
+
+    // Clean up
+    _realmAwareZkClient.deleteRecursively(TEST_VALID_PATH);
+  }
+
+  /**
+   * Test creating a TTL node.
+   */
+  @Test(dependsOnMethods = "testRealmAwareZkClientCreateSequentialWithTTL")
+  public void testRealmAwareZkClientCreateWithTTL() {
+    // Create a dummy ZNRecord
+    ZNRecord znRecord = new ZNRecord("DummyRecord");
+    znRecord.setSimpleField("Dummy", "Value");
+
+    // Test with createParents = true
+    long ttl = 1L;
+    _realmAwareZkClient.createPersistentWithTTL(TEST_VALID_PATH, true, ttl);
+    Assert.assertTrue(_realmAwareZkClient.exists(TEST_VALID_PATH));
+
+    // Test writing and reading data
+    String childPath = TEST_VALID_PATH + "/child";
+    _realmAwareZkClient.createPersistentWithTTL(childPath, znRecord, ttl);
+    ZNRecord retrievedRecord = _realmAwareZkClient.readData(childPath);
+    Assert.assertEquals(znRecord.getSimpleField("Dummy"),
+        retrievedRecord.getSimpleField("Dummy"));
+
+    // Clean up
+    _realmAwareZkClient.deleteRecursively(TEST_VALID_PATH);
+    System.clearProperty("zookeeper.extendedTypesEnabled");
+  }
+
   /*
    * Tests the persistent create() call against a valid path and an invalid path.
    * Valid path is one that belongs to the realm designated by the sharding key.
    * Invalid path is one that does not belong to the realm designated by the sharding key.
    */
-  @Test(dependsOnMethods = "testUnsupportedOperations")
+  @Test(dependsOnMethods = "testRealmAwareZkClientCreateWithTTL")
   public void testCreatePersistent() {
-    _realmAwareZkClient.setZkSerializer(new ZNRecordSerializer());
-
     // Create a dummy ZNRecord
     ZNRecord znRecord = new ZNRecord("DummyRecord");
     znRecord.setSimpleField("Dummy", "Value");