You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 8 Next »

Motivation

Currently (in BookKeeper 4.5) we have several overloaded versions of the methods createLedger/createLedegerAdv/asyncCreateLeader/asyncCreateLeaderAdv. This methods are present because from version to version we added new configuration options for the Ledger.

In order to support new features in the future we need to have a more extensible API.

Proposed Change

So we will introduce a new set of APIs to construct Ledgers, in the future this pattern will be extended to other operations, like deleteLedger/closeLedger/addEntry.

This is how the client code will look like:

 BookKeeper bookeeper = ....;
 CompletableFuture<LedgerHandler> future = bookkeeper.createLedger()
    .withEnsembleSize(3)
    .withWriteQuorumSize(2)
    .withAckQuorumSize(1)
    .withDigestType(DigestType.CRC32)                                       
    .withCustomMetadata(metadata)
    .withPassword(password)
    .withAdvancedOperations(true|false)
    .execute();
LedgerHandler lh = future.get();

In order to achieve this goal we are going to introduce a ICreateBuilder interface

interface ICreateBuilder {
     ICreateBuilder withEnsembleSize(...);
     ICreateBuilder withWriteQuorumSize(...);
     ...
 
     // old style callbacks
     void execute(CreateCallback callback, Object ctx);
     // support java8 completable future
     CompletableFuture<WritableLedgerHandler> execute();
     // sync method
     WritableLedgerHandler create() throws BKException, InterruptedException;
 }

And we will make CrateLedgerOp implement such interface.

We are going to introduce an IBookKeeper interface

interface IBookKeeper { 
      ICreateBuilder createLedger();
      IOpenBuilder   openLedger();
}

We are going to introduce a WritableLedgerHandler interface which contains only the API related to writing to a Ledger.

In a similar way we are going to a ReadableLedegerHandler which contains only the API related to reading to a Ledger and a IOpenBuilder

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

 

Migration Plan and Compatibility

No issue about migration 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

Further works

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

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.

 

Rejected Alternatives

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

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

 

 

  • No labels