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

io.axoniq.eventstore.client.util.FlowControllingStreamObserver Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2017. AxonIQ
 * 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 io.axoniq.eventstore.client.util;

import io.axoniq.eventstore.client.EventStoreConfiguration;
import io.grpc.stub.StreamObserver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Function;
import java.util.function.Predicate;

/**
 */
public class FlowControllingStreamObserver implements StreamObserver {
    private final StreamObserver wrappedStreamObserver;

    private final static Logger logger = LoggerFactory.getLogger(FlowControllingStreamObserver.class);
    private final AtomicLong remainingPermits;
    private final int newPermits;
    private final EventStoreConfiguration configuration;
    private final T newPermitsRequest;
    private final Predicate isConfirmationMessage;

    public FlowControllingStreamObserver(StreamObserver wrappedStreamObserver, EventStoreConfiguration configuration,
                                         Function requestWrapper, Predicate isConfirmationMessage) {
        this.wrappedStreamObserver = wrappedStreamObserver;
        this.configuration = configuration;
        this.remainingPermits = new AtomicLong(configuration.getInitialNrOfPermits()-configuration.getNewPermitsThreshold());
        this.newPermits = configuration.getNrOfNewPermits();
        this.newPermitsRequest = requestWrapper.apply(newPermits);
        this.isConfirmationMessage = isConfirmationMessage;
        wrappedStreamObserver.onNext(requestWrapper.apply(configuration.getInitialNrOfPermits()));
    }

    @Override
    public void onNext(T t) {
        synchronized (wrappedStreamObserver) {
            wrappedStreamObserver.onNext(t);
        }
        logger.debug("Sending response to messaging platform, remaining permits: {}", remainingPermits.get());

        if( isConfirmationMessage.test(t) ) {
            markConsumed(1);
        }
    }

    @Override
    public void onError(Throwable throwable) {
        wrappedStreamObserver.onError(throwable);
    }

    @Override
    public void onCompleted() {
        logger.info("Observer stopped");
        try {
            wrappedStreamObserver.onCompleted();
        } catch(Exception ignore) {

        }
    }

    public void markConsumed(Integer consumed) {
        if( remainingPermits.updateAndGet(old -> old - consumed) == 0) {
            remainingPermits.addAndGet(newPermits);
            synchronized (wrappedStreamObserver) {
                wrappedStreamObserver.onNext(newPermitsRequest);
            }
            logger.debug("Requesting new permits: {}", newPermitsRequest);
        }

    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy