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 org.spongepowered.configurate.reactive;
018
019/**
020 * A subscriber that is transaction-aware. As opposed to standard Subscribers
021 * which receive simple value events, transactional subscribers receive a series
022 * of events: first, a {@code beginTransaction}, followed by a {@code commit}
023 * or {@code rollback}.
024 *
025 * <p>A transactional subscriber will only be fully effective when controlled by
026 * a {@link Processor.Transactional transaction-aware processor}. A
027 * transaction-aware processor will roll back all subscribers if the transaction
028 * fails on any one subscriber, where a standard publisher will not.
029 *
030 * @param <V> the value handled by this subscriber
031 * @since 4.0.0
032 */
033public interface TransactionalSubscriber<V> extends Subscriber<V> {
034
035    @Override
036    default void submit(V item) {
037        try {
038            beginTransaction(item);
039            commit();
040        } catch (TransactionFailedException ex) {
041            rollback();
042        } catch (Exception ex) {
043            rollback();
044            throw ex;
045        }
046    }
047
048    /**
049     * Receive a new value, and validate it.
050     *
051     * <p>The received value must not be made available outside of to other
052     * transaction-aware viewers until {@link #commit()} has been called.</p>
053     *
054     * @param newValue the new value
055     * @throws TransactionFailedException if the new value does not validate
056     * @since 4.0.0
057     */
058    void beginTransaction(V newValue) throws TransactionFailedException;
059
060    /**
061     * Expose a transaction's result.
062     *
063     * <p>This method will be called on all transactional subscribers in a
064     * system have received and validated any new data. Calling this method when
065     * a transaction is not in progress should result in a noop.</p>
066     *
067     * @since 4.0.0
068     */
069    void commit();
070
071    /**
072     * Called when a transaction has failed, to revert any prepared changes.
073     *
074     * <p>This event indicates that it is safe for clients to discard any
075     * prepared information from an in-progress transaction. If there is no
076     * transaction in progress, this must be a no-op.</p>
077     *
078     * @since 4.0.0
079     */
080    void rollback();
081
082}