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

ru.fix.aggregating.profiler.engine.AggregatingCall Maven / Gradle / Ivy

There is a newer version: 1.6.6
Show newest version
package ru.fix.aggregating.profiler.engine;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.fix.aggregating.profiler.Identity;
import ru.fix.aggregating.profiler.ProfiledCall;
import ru.fix.aggregating.profiler.ThrowableRunnable;
import ru.fix.aggregating.profiler.ThrowableSupplier;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Supplier;

/**
 * @author Kamil Asfandiyarov
 */
public class AggregatingCall implements ProfiledCall {
    private static final Logger log = LoggerFactory.getLogger(AggregatingCall.class);

    final AtomicBoolean started = new AtomicBoolean();

    final AtomicLong startNanoTime = new AtomicLong();

    final CallAggregateMutator aggregateMutator;

    final Identity identity;

    public AggregatingCall(Identity identity, CallAggregateMutator aggregateMutator) {
        this.aggregateMutator = aggregateMutator;
        this.identity = identity;
    }

    @Override
    public void call() {
        aggregateMutator.updateAggregate(
                identity,
                aggregate -> aggregate.call(System.currentTimeMillis(), 0, 0));
    }

    @Override
    public void call(double payload) {
        aggregateMutator.updateAggregate(
                identity,
                aggregate -> aggregate.call(System.currentTimeMillis(), 0, payload));
    }

    @Override
    public void call(long startTime) {
        Long currentTime = System.currentTimeMillis();

        aggregateMutator.updateAggregate(
                identity,
                aggregate -> aggregate.call(currentTime, currentTime - startTime, 0));
    }

    @Override
    public void call(long startTime, double payload) {
        Long currentTime = System.currentTimeMillis();

        aggregateMutator.updateAggregate(
                identity,
                aggregate -> aggregate.call(currentTime, currentTime - startTime, payload));
    }

    @Override
    public ProfiledCall start() {
        if (!started.compareAndSet(false, true)) {
            throw new IllegalStateException("Start method was already called." +
                    " Profiled call: " + identity);
        }
        startNanoTime.set(System.nanoTime());

        aggregateMutator.updateAggregate(
                identity,
                aggregate -> aggregate.start(this, System.currentTimeMillis()));
        return this;
    }

    @Override
    public void stop(double payload) {
        if (!started.compareAndSet(true, false)) {
            log.warn("Stop method called on profiler call that currently is not running: {}", identity);
            return;
        }

        updateCountersOnStop(payload);
    }

    @Override
    public void stop() {
        if (!started.compareAndSet(true, false)) {
            log.warn("Stop method called on profiler call that currently is not running: {}", identity);
            return;
        }

        updateCountersOnStop(0);
    }

    private void updateCountersOnStop(double payload) {
        long latencyValue = (System.nanoTime() - startNanoTime.get()) / 1000000;

        aggregateMutator.updateAggregate(
                identity,
                aggregate -> aggregate.stop(this, System.currentTimeMillis(), latencyValue, payload));
    }



    public long startNanoTime() {
        return startNanoTime.get();
    }

    public long timeFromCallStart() {
        return (System.nanoTime() - startNanoTime.get()) / 1000000;
    }

    @Override
    public void stopIfRunning(double payload) {
        if (!started.compareAndSet(true, false)) {
            return;
        }
        updateCountersOnStop(payload);
    }

    @Override
    public  R profile(Supplier block) {
        try {
            start();
            R r = block.get();
            stop();
            return r;
        } finally {
            close();
        }
    }

    @Override
    public  R profileThrowable(ThrowableSupplier block) throws T {
        try {
            start();
            R r = block.get();
            stop();
            return r;
        } finally {
            close();
        }
    }

    @Override
    public  void profileThrowable(ThrowableRunnable block) throws T {
        try {
            start();
            block.run();
            stop();
        } finally {
            close();
        }
    }

    @Override
    public void profile(Runnable block) {
        try {
            start();
            block.run();
            stop();
        } finally {
            close();
        }
    }

    @Override
    public  CompletableFuture profileFuture(Supplier> asyncInvocation) {
        CompletableFuture future;
        try {
            start();
            future = asyncInvocation.get();
        } catch (Throwable exc) {
            close();
            throw exc;
        }

        return future.whenComplete((res, thr) -> {
            if (thr != null) {
                close();
            } else {
                stop();
            }
        });
    }

    @Override
    public  CompletableFuture profileFutureThrowable(ThrowableSupplier, T> asyncInvocation) throws T {
        CompletableFuture future;
        try {
            start();
            future = asyncInvocation.get();
        } catch (Throwable exc) {
            close();
            throw exc;
        }

        return future.whenComplete((res, thr) -> {
            if (thr != null) {
                close();
            } else {
                stop();
            }
        });
    }

    @Override
    public void close() {
        if (!started.compareAndSet(true, false)) {
            // do nothing, if not started or stopped already
            return;
        }
        aggregateMutator.updateAggregate(
                identity,
                aggregate -> aggregate.close(this));
    }

    @Override
    public String toString() {
        return identity.toString();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy