Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Code Block
 BookKeeper bookeeper = ....;
 CompletableFuture<LedgerHandler>CompletableFuture<WriteHandler> future = bookkeeper.createLedger()
    .withEnsembleSize(3)
    .withWriteQuorumSize(2)
    .withAckQuorumSize(1)
    .withDigestType(DigestType.CRC32)                                       
    .withCustomMetadata(metadata)
    .withPassword(password)
    .apply();
WriteHandler lh = future.get();

 CompletableFuture<WriteAdvHandler> future = bookkeeper.createLedger()
    .withEnsembleSize(3)
    .withWriteQuorumSize(2)
    .withAckQuorumSize(1)
    .withDigestType(DigestType.CRC32)                                       
    .withCustomMetadata(metadata)
    .withPassword(password)
    .withAdvancedOperationswithLedgerId(true|falseledgerId)
    .makeAdv()
    .executeapply();
LedgerHandlerWriteAdvHandler lh = future.get();

 

In order to achieve this goal we are going to introduce a ICreateBuilder interfaceCreateBuilder and CreateBuilderAdv interfaces

Code Block
interface ICreateBuilderCreateBuilder {
     ICreateBuilderCreateBuilder withEnsembleSize(...);
     ICreateBuilderCreateBuilder withWriteQuorumSize(...);
     ...
     CreateAdvBuilder makeAdv();

     // old style callbacks
     void execute(CreateCallback callback, Object ctx);
     // support java8 completable future
     CompletableFuture<WriteHandler> apply();
     // sync method
     WriteHandler create() throws BKException, InterruptedException;
 }
interface CreateAdvBuilder {
     CompletableFuture<WritableLedgerHandler> execute// old style callbacks
     void execute(CreateCallback callback, Object ctx);
     // support java8 completable future
     CompletableFuture<WriteAdvHandler> apply();
     // sync method
     WritableLedgerHandlerWriteAdvHandler create() throws BKException, InterruptedException;

}
interface OpenBuilder {
     OpenBuilder withRecovery(boolean)
     OpenBuilder withPassword(password) 
     OpenBuilder withDigestType(digestType)
     CompletableFuture<ReadHandler> apply(long ledgerId)
     void open(long ledgerId, OpenCallback cb, Object ctx)
     ReadHandler open(long ledgerId)
}

And we will make CrateLedgerOp implement such interfaceinterfaces.

We are going to introduce an IBookKeeper a new BookKeeper interface

Code Block
interface BookKeeper extends IBookKeeperAutoCloseable { 
      ICreateBuilderCreateBuilder createLedger();
      IOpenBuilderOpenBuilder   openLedger();
}

We are going to introduce a WritableLedgerHandler interface WriteHandler and WriteHandlerAdv interfaces which contains only the API related to writing to a Ledger, following the LedgerHandler/LedgerHandlerAdv semantics.

In a similar way we are going to introduce a ReadableLedegerHandler ReadHandler which contains only the API related to reading to a Ledger and a IOpenBuilderOpenBuilder.

Please note that WriteHandler and WriteAdvHandler will extend ReadHandler as writer need to be able to read its own writes.

A common Handler interface will be a base interface for ReadHandler and it will contain basic operations like 'close'

Code Block
interface IOpenBuilderHandler extends AutoCloseable {
     IOpenBuildervoid withRecoveryclose(boolean);
     IOpenBuildervoid withPassword(password) asyncClose(CloseCallback cb, Object ctx);
}

interface ReadHandler extends Handler {
     void readEntries();
     IOpenBuilderlong withDigestTypereadLastAddConfirmed(digestType)
     CompleableFuture<ReadableLedgerHandler> execute(long ledgerId);
     .....
     
}
interface WriteHandler extends ReadHandler {
     void addEntry(byte[] data)
     void open(long ledgerId, OpenCallback cb, Object ctxsync(...)
}
interface WriteAdvHandler extends ReadHandler {
     void addEntry(long entryID, byte[] data)
     ReadableLedgerHandlervoid open(long ledgerIdsync(...)
}

 

Migration Plan and Compatibility

...

Legacy methods will be retained. No @Deprecated annotation will be added.

Further removal of existing APIs will be evaluated in the future, maybe while starting a new major release, like 5.0.0

...

We can create similar API style for addEntry, readEntries and other operations which need an extensible API.

 

Open points:

It is to be discussed if we have to create two different interfaces for the simple LedgerHandler and the LedgerHandlerAdv, this will make things more comfortable for developers

An option will be like this

Code Block
interface ICreateBuilder {
     ICreateBuilderAdv withAdvancedOperations()
}

interface ICreateBuilderAdv {
     CompletableFuture<AdvancedWritableLedgerHandler> execute();
}

Maybe AdvancedWritableLedgerHandler should not extend WritableLedgerHandler, because not all the operations on WritableLedgerHandler are available to 'adv' writers, but things will be tricky.

 We would leverage CompletableFuture for operations like close, delete, addEntry, readEntries....

Rejected Alternatives

This is an example of an alternative API which has been rejected, as it will not be really extensible in the future.

The rejected idea is about using the builder pattern for creating LedgerConfiguration structures and not directly ledgers

Code Block
        BookKeeper bookeeper = ....;
        LedgerConfiguration ledgerConfiguration = LedgerConfiguration.builder()
                                                                              .ensembleSize(3)
                                                                              .writeQuorumSize(2)
                                                                              .ackQuorumSize(1)
                                                                              .digestType(DigestType.CRC32)                                       
																			  .customMetadata(Map<String, byte[]> metadata)
                                                                              .password(password)
                                                                              .advanced(true|false);
        LedgerHandle ledger = bookeeper.createLedger(ledgerConfiguration);

...