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();
IWriterHandler lh = future.get();

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

 

In order to achieve this goal we are going to introduce a ICreateBuilder interfaceand ICreateAdvBuilder interfaces

Code Block
interface ICreateBuilder {
     ICreateBuilder withEnsembleSize(...);
     ICreateBuilder withWriteQuorumSize(...);
     ...
     ICreateAdvBuilder makeAdv();

     // old style callbacks
     void execute(CreateCallback callback, Object ctx);
     // support java8 completable future
     CompletableFuture<IWriteHandler> apply();
     // sync method
     IWriteHandler create() throws BKException, InterruptedException;
 }
interface ICreateAdvBuilder {
     // old style callbacks
     void execute(CreateCallback callback, Object ctx);
     // support java8 completable future
     CompletableFuture<IWriteHandlerAdv> apply();
     // sync method
     IWriteHandlerAdv create() throws BKException, InterruptedException;

}

And we will make CrateLedgerOp implement such interfaceinterfaces.

We are going to introduce an IBookKeeper interface

...

We are going to introduce a IWriteHandler interface IWriteHandler and IWriteHandlerAdv 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 IReadHandler which contains only the API related to reading to a Ledger and a IOpenBuilder.

Please note that IWriteHandler and IWriteHandlerAdv will extend IReadHandler as writer need to be able to read its own writes.

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

Code Block
 interface IOpenBuilder {
     IOpenBuilder withRecovery(boolean)
     IOpenBuilder withPassword(password) 
     IOpenBuilder withDigestType(digestType)
     CompleableFuture<IReadHandler> apply(long ledgerId)
     void open(long ledgerId, OpenCallback cb, Object ctx)
     IReadHandler open(long ledgerId)
}

interface ILedgerHandler {
     void close();
     void asyncClose();
}

interface IReadHandler extends ILedgerHandler {
     void readEntries();
     long readLastAddConfirmed();
     .....
     
}
interface IWriteHandler extends IReadHandler {
     void addEntry(byte[] data)
     void sync(...)
}
interface IWriteHandlerAdv extends IReadHandler {
     void addEntry(long entryID, byte[] data)
     void sync(...)
}

 

Migration Plan and Compatibility

...

We can create similar API style for addEntry 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 AdvancedLedgerHandler should not extend WritableLedgerHandler, because not all the operations on WritableLedgerHandler are available to 'adv' writers, but things will be tricky. 

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);

...