001/*
002 * Configurate
003 * Copyright (C) zml and Configurate contributors
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *    http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package ninja.leaping.configurate.reactive;
018
019/**
020 * A subscriber that is transaction-aware. As opposed to standard Subscribers which receive simple value events,
021 * transactional subscribers receive a series of events: first, a {@code beginTransaction}, followed by a {@code commit}
022 * or {@code rollback}.
023 * <p>
024 * A transactional subscriber will only be fully effective when controlled by a {@link Processor.Transactional
025 * transaction-aware publisher}. A transaction-aware publisher will roll back all subscribers if the transaction fails
026 * on any one subscriber, where a standard publisher will not.
027 *
028 * @param <V> The value handled by this subscriber
029 */
030public interface TransactionalSubscriber<V> extends Subscriber<V> {
031    @Override
032    default void submit(V item) {
033        try {
034            beginTransaction(item);
035            commit();
036        } catch (TransactionFailedException ex) {
037            rollback();
038        } catch (Exception ex) {
039            rollback();
040            throw ex;
041        }
042    }
043
044    /**
045     * Receive a new value, and validate it. The received value must not be made available outside of to other
046     * transaction-aware viewers until {@link #commit()} has been called.
047     *
048     * @param newValue The new value
049     * @throws TransactionFailedException if the new value does not validate
050     */
051    void beginTransaction(V newValue) throws TransactionFailedException;
052
053    /**
054     * Expose a transaction's result
055     * <p>
056     * This method will be called on all transactional subscribers in a system have received and validated any new data.
057     * Calling this method when a transaction is not in progress should result in a noop.
058     */
059    void commit();
060
061    /**
062     * Called when a transaction has failed, to revert any prepared changes
063     * <p>
064     * This event indicates that it is safe for clients to discard any prepared information from an in-progress
065     * transaction. If there is no transaction in progress, this must be a no-op.
066     */
067    void rollback();
068}