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

com.microsoft.azure.kusto.ingest.resources.RankedStorageAccount Maven / Gradle / Ivy

There is a newer version: 5.2.0
Show newest version
package com.microsoft.azure.kusto.ingest.resources;

import com.microsoft.azure.kusto.ingest.utils.TimeProvider;

import java.util.ArrayDeque;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class RankedStorageAccount {
    static class Bucket {
        public int successCount;
        public int totalCount;

        public Bucket() {
            this.successCount = 0;
            this.totalCount = 0;
        }
    }

    private final ArrayDeque buckets = new ArrayDeque<>();
    private final ReadWriteLock bucketsLock = new ReentrantReadWriteLock();
    private final String accountName;
    private final int maxNumberOfBuckets;
    private final int bucketDurationMillis;
    private final TimeProvider timeProvider;

    private long lastActionTimestamp;

    public RankedStorageAccount(String accountName, int maxNumberOfBuckets, int bucketDurationMillis, TimeProvider timeProvider) {
        this.accountName = accountName;
        this.maxNumberOfBuckets = maxNumberOfBuckets;
        this.bucketDurationMillis = bucketDurationMillis;
        this.timeProvider = timeProvider;
        lastActionTimestamp = timeProvider.currentTimeMillis();
    }

    public void addResult(boolean success) {
        Bucket lastBucket = adjustForTimePassed();
        lastBucket.totalCount++;
        if (success) {
            lastBucket.successCount++;
        }
    }

    private Bucket adjustForTimePassed() {
        if (buckets.isEmpty()) {
            Bucket b = new Bucket();
            try {
                bucketsLock.writeLock().lock();
                buckets.push(b);
            } finally {
                bucketsLock.writeLock().unlock();
            }
            lastActionTimestamp = timeProvider.currentTimeMillis();
            return b;
        }

        long timePassed = timeProvider.currentTimeMillis() - lastActionTimestamp;
        long bucketsToCreate = timePassed / bucketDurationMillis;
        if (bucketsToCreate == 0) {
            return buckets.peek();
        }

        try {
            bucketsLock.writeLock().lock();
            if (bucketsToCreate >= maxNumberOfBuckets) {
                buckets.clear();
                buckets.push(new Bucket());
            } else {
                for (int i = 0; i < bucketsToCreate; i++) {
                    buckets.push(new Bucket());
                    if (buckets.size() > maxNumberOfBuckets) {
                        buckets.poll();
                    }
                }
            }
        } finally {
            bucketsLock.writeLock().unlock();
        }

        lastActionTimestamp = timeProvider.currentTimeMillis();
        return buckets.peek();
    }

    public double getRank() {
        if (buckets.isEmpty()) {
            // Start assuming the account is good
            return 1;
        }

        int bucketWeight = buckets.size() + 1;
        double rank = 0;
        double totalWeight = 0;

        // For each bucket, calculate the success rate ( success / total ) and multiply it by the bucket weight.
        // The older the bucket, the less weight it has. For example, if there are 3 buckets, the oldest bucket will have
        // a weight of 1, the middle bucket will have a weight of 2 and the newest bucket will have a weight of 3.
        try {
            bucketsLock.readLock().lock();
            for (Bucket bucket : buckets) {
                if (bucket.totalCount == 0) {
                    bucketWeight--;
                    continue;
                }
                double successRate = (double) bucket.successCount / bucket.totalCount;
                rank += successRate * bucketWeight;
                totalWeight += bucketWeight;
                bucketWeight--;
            }
        } finally {
            bucketsLock.readLock().unlock();
        }
        return rank / totalWeight;
    }

    public String getAccountName() {
        return accountName;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy