You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@curator.apache.org by dr...@apache.org on 2017/05/02 20:06:30 UTC

[22/50] curator git commit: Added AsyncResult - still needs documentation

Added AsyncResult - still needs documentation


Project: http://git-wip-us.apache.org/repos/asf/curator/repo
Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/649c4415
Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/649c4415
Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/649c4415

Branch: refs/heads/master
Commit: 649c441529040401e2f414fbaffd8c6122263e70
Parents: 2ef420c
Author: randgalt <ra...@apache.org>
Authored: Sat Jan 21 11:06:36 2017 -0500
Committer: randgalt <ra...@apache.org>
Committed: Sat Jan 21 11:06:36 2017 -0500

----------------------------------------------------------------------
 .../org/apache/curator/x/async/AsyncResult.java | 118 +++++++++++++++
 .../x/async/details/AsyncResultImpl.java        | 142 +++++++++++++++++++
 .../curator/x/async/TestBasicOperations.java    |  40 +++++-
 3 files changed, 299 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/649c4415/curator-x-async/src/main/java/org/apache/curator/x/async/AsyncResult.java
----------------------------------------------------------------------
diff --git a/curator-x-async/src/main/java/org/apache/curator/x/async/AsyncResult.java b/curator-x-async/src/main/java/org/apache/curator/x/async/AsyncResult.java
new file mode 100644
index 0000000..5c99480
--- /dev/null
+++ b/curator-x-async/src/main/java/org/apache/curator/x/async/AsyncResult.java
@@ -0,0 +1,118 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.curator.x.async;
+
+import org.apache.curator.x.async.details.AsyncResultImpl;
+import org.apache.zookeeper.KeeperException;
+import java.util.Optional;
+import java.util.concurrent.CompletionStage;
+
+/**
+ * <p>
+ *     Utility that combines the value, the ZooKeeper result code and the exception in one object
+ *     allowing you to not worry about exceptional completions. i.e. the {@link java.util.concurrent.CompletionStage}
+ *     retured by {@link org.apache.curator.x.async.AsyncResult#of(AsyncStage)} always completes successfully with an
+ *     {@link org.apache.curator.x.async.AsyncResult} object.
+ * </p>
+ *
+ * <p>
+ *     All three possible results from a ZooKeeper method are encapsulated in this object. If the ZooKeeper
+ *     method succeeds, the internal value will be set. If there was a standard ZooKeeper error code
+ *     ({@link org.apache.zookeeper.KeeperException.Code#NODEEXISTS}, etc.), that code is set and the
+ *     value is null. If there was a general exception, that exception is set, the value will be null
+ *     and the code will be {@link org.apache.zookeeper.KeeperException.Code#SYSTEMERROR}.
+ * </p>
+ * @param <T> value type
+ */
+public interface AsyncResult<T>
+{
+    /**
+     * Return a new stage that wraps an async stage into a result-style completion stage. The returned
+     * CompletionStage will always complete successfully.
+     *
+     * @param stage the stage to wrap
+     * @param <T> value type
+     * @return completion stage that resolves to a result
+     */
+    static <T> CompletionStage<AsyncResult<T>> of(AsyncStage<T> stage)
+    {
+        return stage.handle((value, ex) -> {
+            if ( ex != null )
+            {
+                if ( ex instanceof KeeperException )
+                {
+                    return new AsyncResultImpl<T>(((KeeperException)ex).code());
+                }
+                return new AsyncResultImpl<T>(ex);
+            }
+            return new AsyncResultImpl<T>(value);
+        });
+    }
+
+    /**
+     * Returns the raw result of the ZooKeeper method or <code>null</code>
+     *
+     * @return result or <code>null</code>
+     */
+    T getRawValue();
+
+    /**
+     * An optional wrapper around the ZooKeeper method result
+     *
+     * @return wrapped result
+     */
+    Optional<T> getValue();
+
+    /**
+     * Return the ZooKeeper result code. If the method was successful,
+     * {@link org.apache.zookeeper.KeeperException.Code#OK} is returned. If there was a general
+     * exception {@link org.apache.zookeeper.KeeperException.Code#SYSTEMERROR} is returned.
+     *
+     * @return result code
+     */
+    KeeperException.Code getCode();
+
+    /**
+     * Return any general exception or <code>null</code>
+     *
+     * @return exception or <code>null</code>
+     */
+    Throwable getRawException();
+
+    /**
+     * An optional wrapper around any general exception
+     *
+     * @return wrapped exception
+     */
+    Optional<Throwable> getException();
+
+    /**
+     * If there was a general exception (but <strong>not</strong> a {@link org.apache.zookeeper.KeeperException})
+     * a {@link java.lang.RuntimeException} is thrown that wraps the exception. Otherwise, the method returns
+     * without any action being performed.
+     */
+    void checkException();
+
+    /**
+     * If there was a general exception or a {@link org.apache.zookeeper.KeeperException}
+     * a {@link java.lang.RuntimeException} is thrown that wraps the exception. Otherwise, the method returns
+     * without any action being performed.
+     */
+    void checkError();
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/649c4415/curator-x-async/src/main/java/org/apache/curator/x/async/details/AsyncResultImpl.java
----------------------------------------------------------------------
diff --git a/curator-x-async/src/main/java/org/apache/curator/x/async/details/AsyncResultImpl.java b/curator-x-async/src/main/java/org/apache/curator/x/async/details/AsyncResultImpl.java
new file mode 100644
index 0000000..c555b83
--- /dev/null
+++ b/curator-x-async/src/main/java/org/apache/curator/x/async/details/AsyncResultImpl.java
@@ -0,0 +1,142 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.curator.x.async.details;
+
+import org.apache.curator.x.async.AsyncResult;
+import org.apache.zookeeper.KeeperException;
+import java.util.Objects;
+import java.util.Optional;
+
+public class AsyncResultImpl<T> implements AsyncResult<T>
+{
+    private final T value;
+    private final KeeperException.Code code;
+    private final Throwable exception;
+
+    public AsyncResultImpl()
+    {
+        this(null, KeeperException.Code.OK, null);
+    }
+
+    public AsyncResultImpl(KeeperException.Code code)
+    {
+        this(null, code, null);
+    }
+
+    public AsyncResultImpl(T value)
+    {
+        this(value, KeeperException.Code.OK, null);
+    }
+
+    public AsyncResultImpl(Throwable exception)
+    {
+        this(null, KeeperException.Code.SYSTEMERROR, exception);
+    }
+
+    private AsyncResultImpl(T value, KeeperException.Code code, Throwable exception)
+    {
+        this.value = value;
+        this.exception = exception;
+        this.code = Objects.requireNonNull(code, "error cannot be null");
+    }
+
+    public T getRawValue()
+    {
+        return value;
+    }
+
+    public Optional<T> getValue()
+    {
+        return Optional.ofNullable(value);
+    }
+
+    public KeeperException.Code getCode()
+    {
+        return code;
+    }
+
+    public Throwable getRawException()
+    {
+        return exception;
+    }
+
+    public Optional<Throwable> getException()
+    {
+        return Optional.ofNullable(exception);
+    }
+
+    public void checkException()
+    {
+        if ( exception != null )
+        {
+            throw new RuntimeException(exception);
+        }
+    }
+
+    @Override
+    public void checkError()
+    {
+        checkException();
+        if ( code != KeeperException.Code.OK )
+        {
+            throw new RuntimeException(KeeperException.create(code));
+        }
+    }
+
+    @Override
+    public boolean equals(Object o)
+    {
+        if ( this == o )
+        {
+            return true;
+        }
+        if ( o == null || getClass() != o.getClass() )
+        {
+            return false;
+        }
+
+        AsyncResultImpl<?> that = (AsyncResultImpl<?>)o;
+
+        if ( value != null ? !value.equals(that.value) : that.value != null )
+        {
+            return false;
+        }
+        //noinspection SimplifiableIfStatement
+        if ( code != that.code )
+        {
+            return false;
+        }
+        return exception != null ? exception.equals(that.exception) : that.exception == null;
+    }
+
+    @Override
+    public int hashCode()
+    {
+        int result = value != null ? value.hashCode() : 0;
+        result = 31 * result + code.hashCode();
+        result = 31 * result + (exception != null ? exception.hashCode() : 0);
+        return result;
+    }
+
+    @Override
+    public String toString()
+    {
+        return "AsyncResult{" + "value=" + value + ", code=" + code + ", exception=" + exception + '}';
+    }
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/649c4415/curator-x-async/src/test/java/org/apache/curator/x/async/TestBasicOperations.java
----------------------------------------------------------------------
diff --git a/curator-x-async/src/test/java/org/apache/curator/x/async/TestBasicOperations.java b/curator-x-async/src/test/java/org/apache/curator/x/async/TestBasicOperations.java
index 34c02aa..1c4f241 100644
--- a/curator-x-async/src/test/java/org/apache/curator/x/async/TestBasicOperations.java
+++ b/curator-x-async/src/test/java/org/apache/curator/x/async/TestBasicOperations.java
@@ -55,7 +55,7 @@ public class TestBasicOperations extends BaseClassForTests
     {
         super.setup();
 
-        CuratorFramework client = CuratorFrameworkFactory.newClient(server.getConnectString(), new RetryOneTime(timing.milliseconds()));
+        CuratorFramework client = CuratorFrameworkFactory.newClient(server.getConnectString(), new RetryOneTime(timing.forSleepingABit().milliseconds()));
         client.start();
         this.client = AsyncCuratorFramework.wrap(client);
     }
@@ -144,6 +144,44 @@ public class TestBasicOperations extends BaseClassForTests
         Assert.assertTrue(timing.awaitLatch(latch));
     }
 
+    @Test
+    public void testResultWrapper() throws Exception
+    {
+        CompletionStage<AsyncResult<String>> resultStage = AsyncResult.of(client.create().forPath("/first"));
+        complete(resultStage, (v, e) -> {
+            Assert.assertNull(e);
+            Assert.assertEquals(v.getRawValue(), "/first");
+            Assert.assertNull(v.getRawException());
+            Assert.assertEquals(v.getCode(), KeeperException.Code.OK);
+        });
+
+        resultStage = AsyncResult.of(client.create().forPath("/foo/bar"));
+        complete(resultStage, (v, e) -> {
+            Assert.assertNull(e);
+            Assert.assertNull(v.getRawValue());
+            Assert.assertNull(v.getRawException());
+            Assert.assertEquals(v.getCode(), KeeperException.Code.NONODE);
+        });
+
+        resultStage = AsyncResult.of(client.create().forPath("illegal path"));
+        complete(resultStage, (v, e) -> {
+            Assert.assertNull(e);
+            Assert.assertNull(v.getRawValue());
+            Assert.assertNotNull(v.getRawException());
+            Assert.assertTrue(v.getRawException() instanceof IllegalArgumentException);
+            Assert.assertEquals(v.getCode(), KeeperException.Code.SYSTEMERROR);
+        });
+
+        server.stop();
+        resultStage = AsyncResult.of(client.create().forPath("/second"));
+        complete(resultStage, (v, e) -> {
+            Assert.assertNull(e);
+            Assert.assertNull(v.getRawValue());
+            Assert.assertNull(v.getRawException());
+            Assert.assertEquals(v.getCode(), KeeperException.Code.CONNECTIONLOSS);
+        });
+    }
+
     private <T, U> void complete(CompletionStage<T> stage)
     {
         complete(stage, (v, e) -> {});