| /* |
| * Copyright © 2014 Cask Data, Inc. |
| * |
| * Licensed 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 co.cask.tephra; |
| |
| import java.util.Collection; |
| |
| /** |
| * Interface to be implemented by a component that interacts with transaction logic. |
| * <p/> |
| * The client code that uses transaction logic looks like this: |
| * <pre> |
| * TransactionAware dataSet = // ... // dataSet is one example of component that interacts with tx logic |
| * |
| * Transaction tx = txClient.start(); |
| * dataSet.startTx(tx); // notifying about new transaction |
| * dataSet.write(...); |
| * // ... do other operations on dataSet |
| * Collection<byte[]> changes = dataSet.getTxChanges(); |
| * boolean rollback = true; |
| * if (txClient.canCommit(changes)) { // checking conflicts before commit, if none, commit tx |
| * if (dataSet.commitTx()) { // try persisting changes |
| * if (txClient.commit(tx)) { // if OK, make tx visible; if not - tx stays invisible to others |
| * dataSet.postTxCommit(); // notifying dataset about tx commit success via callback |
| * rollback = false; |
| * } |
| * } |
| * } |
| * |
| * if (rollback) { // if there are conflicts (or cannot commit), try rollback changes |
| * if (dataSet.rollbackTx()) { // try undo changes |
| * txClient.abort(tx); // if OK, make tx visible; if not - tx stays invisible to others |
| * } |
| * } |
| * |
| * </pre> |
| */ |
| // todo: use custom exception class? |
| // todo: review exception handling where it is used |
| // todo: add flush()? nah - flush is same as commitTx() actually |
| // todo: add onCommitted() - so that e.g. hbase table can do *actual* deletes at this point |
| public interface TransactionAware { |
| /** |
| * Called when new transaction has started. This may reset any state which has been left behind by the previous |
| * transaction. |
| * |
| * @param tx transaction info |
| */ |
| // todo: rename to onTxStart() |
| void startTx(Transaction tx); |
| |
| /** |
| * Called when the state of the current transaction has been updated. This should replace any reference to the |
| * current {@link Transaction} held by this {@code TransactionAware}, but should <strong>not</strong> reset |
| * any state (such as the write change sets) that is currently maintained. |
| * |
| * @param tx the updated transaction |
| */ |
| void updateTx(Transaction tx); |
| |
| /** |
| * @return changes made by current transaction to be used for conflicts detection before commit. |
| */ |
| Collection<byte[]> getTxChanges(); |
| |
| /** |
| * Called before transaction has been committed. |
| * Can be used e.g. to flush changes cached in-memory to persistent store. |
| * @return true if transaction can be committed, otherwise false. |
| */ |
| // todo: rename to beforeTxCommit() |
| boolean commitTx() throws Exception; |
| |
| /** |
| * Called after transaction has been committed. |
| * Can be used e.g. evict entries from a cache etc. Because this is called after the transaction is committed, |
| * the success or failure of the transaction cannot depend on it. Hence this method returns nothing and it is not |
| * expected to throw exceptions. |
| * @throws RuntimeException in case of serious failure that should not be ignored. |
| */ |
| void postTxCommit(); |
| |
| /** |
| * Called during transaction rollback (for whatever reason: conflicts, errors, etc.). |
| * @return true if all changes made during transaction were rolled back, false otherwise (e.g. if more cleanup needed |
| * or changes cannot be undone). True also means that this transaction can be made visible to others without |
| * breaking consistency of the data: since all changes were undone there's "nothing to see". |
| */ |
| // todo: rename to onTxRollback() |
| boolean rollbackTx() throws Exception; |
| |
| /** |
| * Used for error reporting. |
| */ |
| // todo: use toString() instead everywhere |
| String getTransactionAwareName(); |
| } |