All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.robozonky.app.tenant.TransactionalPowerTenantImpl Maven / Gradle / Ivy

/*
 * Copyright 2020 The RoboZonky Project
 *
 * 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 com.github.robozonky.app.tenant;

import java.util.Optional;
import java.util.Queue;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.function.Function;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import com.github.robozonky.api.Money;
import com.github.robozonky.api.SessionInfo;
import com.github.robozonky.api.notifications.SessionEvent;
import com.github.robozonky.api.remote.entities.Loan;
import com.github.robozonky.api.strategies.InvestmentStrategy;
import com.github.robozonky.api.strategies.PurchaseStrategy;
import com.github.robozonky.api.strategies.ReservationStrategy;
import com.github.robozonky.api.strategies.SellStrategy;
import com.github.robozonky.internal.async.Reloadable;
import com.github.robozonky.internal.remote.Zonky;
import com.github.robozonky.internal.state.InstanceState;
import com.github.robozonky.internal.tenant.Availability;
import com.github.robozonky.internal.tenant.LazyEvent;
import com.github.robozonky.internal.tenant.RemotePortfolio;

class TransactionalPowerTenantImpl implements TransactionalPowerTenant {

    private static final Logger LOGGER = LogManager.getLogger(TransactionalPowerTenantImpl.class);

    private final PowerTenant parent;
    private final Reloadable delayedFiring = Reloadable.with(DelayedFiring::new)
        .build();
    private final Queue stateUpdates = new ConcurrentLinkedQueue<>();

    public TransactionalPowerTenantImpl(final PowerTenant parent) {
        this.parent = parent;
    }

    private DelayedFiring getDelayedFiring() {
        return delayedFiring.get()
            .get();
    }

    @Override
    public void setKnownBalanceUpperBound(final Money knownBalanceUpperBound) {
        parent.setKnownBalanceUpperBound(knownBalanceUpperBound);
    }

    @Override
    public Money getKnownBalanceUpperBound() {
        return parent.getKnownBalanceUpperBound();
    }

    @Override
    public CompletableFuture fire(final SessionEvent event) {
        LOGGER.trace("Event stored within transaction: {}.", event);
        return getDelayedFiring().delay(() -> parent.fire(event));
    }

    @Override
    public CompletableFuture fire(final LazyEvent event) {
        LOGGER.trace("Lazy event stored within transaction: {}.", event);
        return getDelayedFiring().delay(() -> parent.fire(event));
    }

    @Override
    public void commit() {
        LOGGER.debug("Replaying transaction.");
        while (!stateUpdates.isEmpty()) {
            stateUpdates.poll()
                .run();
        }
        getDelayedFiring().run();
        LOGGER.debug("Done.");
    }

    @Override
    public void abort() {
        LOGGER.debug("Aborting transaction.");
        stateUpdates.clear();
        getDelayedFiring().cancel();
        delayedFiring.clear();
    }

    @Override
    public  T call(final Function operation) {
        return parent.call(operation);
    }

    @Override
    public Availability getAvailability() {
        return parent.getAvailability();
    }

    @Override
    public RemotePortfolio getPortfolio() {
        return parent.getPortfolio();
    }

    @Override
    public SessionInfo getSessionInfo() {
        return parent.getSessionInfo();
    }

    @Override
    public Optional getInvestmentStrategy() {
        return parent.getInvestmentStrategy();
    }

    @Override
    public Optional getSellStrategy() {
        return parent.getSellStrategy();
    }

    @Override
    public Optional getPurchaseStrategy() {
        return parent.getPurchaseStrategy();
    }

    @Override
    public Optional getReservationStrategy() {
        return parent.getReservationStrategy();
    }

    @Override
    public Loan getLoan(final int loanId) {
        return parent.getLoan(loanId);
    }

    @Override
    public  InstanceState getState(final Class clz) {
        LOGGER.trace("Creating transactional instance state for {}.", clz);
        return new TransactionalInstanceState<>(stateUpdates, parent.getState(clz));
    }

    @Override
    public void close() {
        LOGGER.trace("Closing.");
        if (!stateUpdates.isEmpty()) {
            throw new IllegalStateException("There are uncommitted changes.");
        }
        if (getDelayedFiring().isPending()) {
            throw new IllegalStateException("There are uncommitted events.");
        }
    }

    @Override
    public String toString() {
        return "TransactionalPowerTenantImpl{" +
                "parent=" + parent +
                '}';
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy