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

com.yahoo.vespa.config.server.TimeoutBudget Maven / Gradle / Ivy

There is a newer version: 8.441.21
Show newest version
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.config.server;

import com.yahoo.concurrent.UncheckedTimeoutException;

import java.time.Clock;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;

/**
 * Handles a timeout logic by providing higher level abstraction for asking if there is time left.
 *
 * @author Ulf Lilleengen
 */
public class TimeoutBudget {

    private final Clock clock;
    private final Instant startTime;
    private final List measurements = new ArrayList<>();
    private final Instant endTime;

    public TimeoutBudget(Clock clock, Duration duration) {
        this.clock = clock;
        this.startTime = clock.instant();
        this.endTime = startTime.plus(duration);
    }

    public Duration timeout() {
        return Duration.between(startTime, endTime);
    }

    public Duration timeLeft() {
        Instant now = clock.instant();
        Duration duration = Duration.between(now, endTime);
        return duration.isNegative() ? Duration.ZERO : duration;
    }

    public boolean hasTimeLeft() {
        return clock.instant().isBefore(endTime);
    }

    public boolean hasTimeLeft(String step) {
        Instant now = clock.instant();
        measurements.add(new Measurement(now, step));
        return now.isBefore(endTime);
    }

    public String timesUsed() {
        StringBuilder buf = new StringBuilder();
        buf.append("[");
        Instant prev = startTime;
        for (Measurement m : measurements) {
            if ( ! m.label().isEmpty()) {
                buf.append(m.label()).append(": ");
            }
            buf.append(Duration.between(prev, m.timestamp()).toMillis())
                    .append(" ms")
                    .append(", ");
            prev = m.timestamp();
        }
        Instant now = clock.instant();
        buf.append("total: ");
        buf.append(Duration.between(startTime, now).toMillis());
        buf.append(" ms]");
        return buf.toString();
    }

    /**
     * @param exceptionMessage exception message for the exception that will be thrown if there is no time left
     * @throws UncheckedTimeoutException if this has no time left
     */
    public void assertNotTimedOut(Supplier exceptionMessage) {
        if (hasTimeLeft()) return;
        throw new UncheckedTimeoutException(exceptionMessage.get());
    }

    private static class Measurement {

        private final Instant timestamp;
        private final String label;

        Measurement(Instant timestamp, String label) {
            this.timestamp = timestamp;
            this.label = label;
        }

        public Instant timestamp() {
            return timestamp;
        }

        public String label() {
            return label;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy