You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@bookkeeper.apache.org by GitBox <gi...@apache.org> on 2017/11/24 20:29:07 UTC

[GitHub] sijie closed pull request #764: Issue-553: Documentation for new fluent API

sijie closed pull request #764: Issue-553: Documentation for new fluent API
URL: https://github.com/apache/bookkeeper/pull/764
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/site/docs/4.6.0/api/ledger-api.md b/site/docs/4.6.0/api/ledger-api.md
index 8aa42ce8e..acde8d695 100644
--- a/site/docs/4.6.0/api/ledger-api.md
+++ b/site/docs/4.6.0/api/ledger-api.md
@@ -471,3 +471,277 @@ mvn exec:java -Dexec.mainClass=org.apache.bookkeeper.Dice
 Value = 3, isLeader = true
 Value = 1, isLeader = false
 ```
+
+## New API
+
+Since 4.6 BookKeeper provides a new client API which leverages Java8 [CompletableFuture](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html) facility.
+[WriteHandle](../javadoc/org/apache/bookkeeper/client/api/WriteHandle), [WriteAdvHandle](../javadoc/org/apache/bookkeeper/client/api/WriteAdvHandle), [ReadHandle](../javadoc/org/apache/bookkeeper/client/api/ReadHandle) are introduced for replacing the generic [LedgerHandle](../javadoc/org/apache/bookkeeper/client/LedgerHandle).
+
+> All the new API now is available in `org.apache.bookkeeper.client.api`. You should only use interfaces defined in this package.
+
+*Beware* that this API in 4.6 is still experimental API and can be subject to changes in next minor releases.
+
+### Create a new client
+
+In order to create a new [`BookKeeper`](../javadoc/org/apache/bookkeeper/client/api/BookKeeper) client object, you need to construct a [`ClientConfiguration`](../javadoc/org/apache/bookkeeper/conf/ClientConfiguration) object and set a [connection string](#connection-string) first, and then use [`BookKeeperBuilder`](../javadoc/org/apache/bookkeeper/client/api/BookKeeperBuilder) to build the client.
+
+Here is an example building the bookkeeper client.
+
+```java
+// construct a client configuration instance
+ClientConfiguration conf = new ClientConfiguration();
+conf.setZkServers(zkConnectionString);
+conf.setZkLedgersRootPath("/path/to/ledgers/root");
+
+// build the bookkeeper client
+BookKeeper bk = BookKeeper.newBuilder(conf)
+    .statsLogger(...)
+    ...
+    .build();
+
+```
+
+### Create ledgers
+
+the easiest way to create a {% pop ledger %} using the java client is via the [`createbuilder`](../javadoc/org/apache/bookkeeper/client/api/createbuilder). you must specify at least
+a [`digesttype`](../javadoc/org/apache/bookkeeper/client/api/digesttype) and a password.
+
+here's an example:
+
+```java
+BookKeeper bk = ...;
+
+byte[] password = "some-password".getBytes();
+
+WriteHandle wh = bk.newCreateLedgerOp()
+    .withDigestType(DigestType.CRC32)
+    .withPassword(password)
+    .withEnsembleSize(3)
+    .withWriteQuorumSize(3)
+    .withAckQuorumSize(2)
+    .execute()          // execute the creation op
+    .get();             // wait for the execution to complete
+```
+
+A [`WriteHandle`](../javadoc/org/apache/bookkeeper/client/api/WriteHandle) is returned for applications to write and read entries to and from the ledger.
+
+### Append entries to ledgers
+
+The [`WriteHandle`](../javadoc/org/apache/bookkeeper/client/api/WriteHandle) can be used for applications to append entries to the ledgers.
+
+```java
+WriteHandle wh = ...;
+
+CompletableFuture<Long> addFuture = wh.append("Some entry data".getBytes());
+
+// option 1: you can wait for add to complete synchronously
+try {
+    long entryId = FutureUtils.result(addFuture.get());
+} catch (BKException bke) {
+    // error handling
+}
+
+// option 2: you can process the result and exception asynchronously
+addFuture
+    .thenApply(entryId -> {
+        // process the result
+    })
+    .exceptionally(cause -> {
+        // handle the exception
+    })
+
+// option 3: bookkeeper provides a twitter-future-like event listener for processing result and exception asynchronously
+addFuture.whenComplete(new FutureEventListener() {
+    @Override
+    public void onSuccess(long entryId) {
+        // process the result
+    }
+    @Override
+    public void onFailure(Throwable cause) {
+        // handle the exception
+    }
+});
+```
+
+The append method supports three representations of a bytes array: the native java `byte[]`, java nio `ByteBuffer` and netty `ByteBuf`.
+It is recommended to use `ByteBuf` as it is more gc friendly.
+
+### Open ledgers
+
+You can open ledgers to read entries. Opening ledgers is done by [`openBuilder`](../javadoc/org/apache/bookkeeper/client/api/openBuilder). You must specify the ledgerId and the password
+in order to open the ledgers.
+
+here's an example:
+
+```java
+BookKeeper bk = ...;
+
+long ledgerId = ...;
+byte[] password = "some-password".getBytes();
+
+ReadHandle rh = bk.newOpenLedgerOp()
+    .withLedgerId(ledgerId)
+    .withPassword(password)
+    .execute()          // execute the open op
+    .get();             // wait for the execution to complete
+```
+
+A [`ReadHandle`](../javadoc/org/apache/bookkeeper/client/api/ReadHandle) is returned for applications to read entries to and from the ledger.
+
+#### Recovery vs NoRecovery
+
+By default, the [`openBuilder`](../javadoc/org/apache/bookkeeper/client/api/openBuilder) opens the ledger in a `NoRecovery` mode. You can open the ledger in `Recovery` mode by specifying
+`withRecovery(true)` in the open builder.
+
+```java
+BookKeeper bk = ...;
+
+long ledgerId = ...;
+byte[] password = "some-password".getBytes();
+
+ReadHandle rh = bk.newOpenLedgerOp()
+    .withLedgerId(ledgerId)
+    .withPassword(password)
+    .withRecovery(true)
+    .execute()
+    .get();
+
+```
+
+**What is the difference between "Recovery" and "NoRecovery"?**
+
+If you are opening a ledger in "Recovery" mode, it will basically fence and seal the ledger -- no more entries are allowed
+to be appended to it. The writer which is currently appending entries to the ledger will fail with [`LedgerFencedException`](../javadoc/org/apache/bookkeeper/client/api/BKException.Code#LedgerFencedException).
+
+In constrat, opening a ledger in "NoRecovery" mode, it will not fence and seal the ledger. "NoRecovery" mode is usually used by applications to tailing-read from a ledger.
+
+### Read entries from ledgers
+
+The [`ReadHandle`](../javadoc/org/apache/bookkeeper/client/api/ReadHandle) returned from the open builder can be used for applications to read entries from the ledgers.
+
+```java
+ReadHandle rh = ...;
+
+long startEntryId = ...;
+long endEntryId = ...;
+CompletableFuture<LedgerEntries> readFuture = rh.read(startEntryId, endEntryId);
+
+// option 1: you can wait for read to complete synchronously
+try {
+    LedgerEntries entries = FutureUtils.result(readFuture.get());
+} catch (BKException bke) {
+    // error handling
+}
+
+// option 2: you can process the result and exception asynchronously
+readFuture
+    .thenApply(entries -> {
+        // process the result
+    })
+    .exceptionally(cause -> {
+        // handle the exception
+    })
+
+// option 3: bookkeeper provides a twitter-future-like event listener for processing result and exception asynchronously
+readFuture.whenComplete(new FutureEventListener<>() {
+    @Override
+    public void onSuccess(LedgerEntries entries) {
+        // process the result
+    }
+    @Override
+    public void onFailure(Throwable cause) {
+        // handle the exception
+    }
+});
+```
+
+Once you are done with processing the [`LedgerEntries`](../javadoc/org/apache/bookkeeper/client/api/LedgerEntries), you can call `#close()` on the `LedgerEntries` instance to
+release the buffers held by it.
+
+Applications are allowed to read any entries between `0` and [`LastAddConfirmed`](../javadoc/org/apache/bookkeeper/client/api/ReadHandle.html#getLastAddConfirmed). If the applications
+attempts to read entries beyond `LastAddConfirmed`, they will receive [`IncorrectParameterException`](../javadoc/org/apache/bookkeeper/client/api/BKException.Code#IncorrectParameterException).
+
+### Read unconfirmed entries from ledgers
+
+`readUnconfirmed` is provided the mechanism for applications to read entries beyond `LastAddConfirmed`. Applications should be aware of `readUnconfirmed` doesn't provide any
+repeatable read consistency.
+
+```java
+CompletableFuture<LedgerEntries> readFuture = rh.readUnconfirmed(startEntryId, endEntryId);
+```
+
+### Tailing Reads
+
+There are two methods for applications to achieve tailing reads: `Polling` and `Long-Polling`.
+
+#### Polling
+
+You can do this in synchronous way:
+
+```java
+ReadHandle rh = ...;
+
+long startEntryId = 0L;
+long nextEntryId = startEntryId;
+int numEntriesPerBatch = 4;
+while (!rh.isClosed() || nextEntryId <= rh.getLastAddConfirmed()) {
+    long lac = rh.getLastAddConfirmed();
+    if (nextEntryId > lac) {
+        // no more entries are added
+        Thread.sleep(1000);
+
+        lac = rh.readLastAddConfirmed().get();
+        continue;
+    }
+
+    long endEntryId = Math.min(lac, nextEntryId + numEntriesPerBatch - 1);
+    LedgerEntries entries = rh.read(nextEntryId, endEntryId).get();
+
+    // process the entries
+
+    nextEntryId = endEntryId + 1;
+}
+```
+
+#### Long Polling
+
+```java
+ReadHandle rh = ...;
+
+long startEntryId = 0L;
+long nextEntryId = startEntryId;
+int numEntriesPerBatch = 4;
+while (!rh.isClosed() || nextEntryId <= rh.getLastAddConfirmed()) {
+    long lac = rh.getLastAddConfirmed();
+    if (nextEntryId > lac) {
+        // no more entries are added
+        try (LastConfirmedAndEntry lacAndEntry = rh.readLastAddConfirmedAndEntry(nextEntryId, 1000, false).get()) {
+            if (lacAndEntry.hasEntry()) {
+                // process the entry
+
+                ++nextEntryId;
+            }
+        }
+    } else {
+        long endEntryId = Math.min(lac, nextEntryId + numEntriesPerBatch - 1);
+        LedgerEntries entries = rh.read(nextEntryId, endEntryId).get();
+
+        // process the entries
+        nextEntryId = endEntryId + 1;
+    }
+}
+```
+
+### Delete ledgers
+
+{% pop Ledgers %} can be deleted by using [`DeleteBuilder`](../javadoc/org/apache/bookkeeper/client/api/DeleteBuilder).
+
+```java
+BookKeeper bk = ...;
+long ledgerId = ...;
+
+bk.newDeleteLedgerOp()
+    .withLedgerId(ledgerId)
+    .execute()
+    .get();
+```
diff --git a/site/docs/latest/api/ledger-adv-api.md b/site/docs/latest/api/ledger-adv-api.md
index f46950dd9..df6224dd7 100644
--- a/site/docs/latest/api/ledger-adv-api.md
+++ b/site/docs/latest/api/ledger-adv-api.md
@@ -60,6 +60,26 @@ LedgerHandleAdv handle = bkClient.createLedgerAdv(
 > If a ledger already exists when users try to create an advanced ledger with same ledger id,
 > a [LedgerExistsException](../javadoc/org/apache/bookkeeper/client/BKException.BKLedgerExistException.html) is thrown by the bookkeeper client.
 
+Creating advanced ledgers can be done throught a fluent API since 4.6.
+
+```java
+BookKeeper bk = ...;
+
+byte[] passwd = "some-passwd".getBytes();
+
+WriteHandle wh = bk.newCreateLedgerOp()
+    .withDigestType(DigestType.CRC32)
+    .withPassword(passwd)
+    .withEnsembleSize(3)
+    .withWriteQuorumSize(3)
+    .withAckQuorumSize(2)
+    .makeAdv()                  // convert the create ledger builder to create ledger adv builder
+    .withLedgerId(1234L)
+    .execute()                  // execute the creation op
+    .get();                     // wait for the execution to complete
+
+```
+
 ### Add Entries
 
 The normal [add entries api](ledger-api/#adding-entries-to-ledgers) in advanced ledgers are disabled. Instead, when users want to add entries
@@ -71,6 +91,15 @@ long entryId = ...; // entry id generated externally
 ledger.addEntry(entryId, "Some entry data".getBytes());
 ```
 
+If you are using the new API, you can do as following:
+
+```java
+WriteHandle wh = ...;
+long entryId = ...; // entry id generated externally
+
+wh.write(entryId, "Some entry data".getBytes()).get();
+```
+
 A few notes when using this API:
 
 - The entry id has to be non-negative.


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services