azkustoingest/internal/resources/ranked_storage_account_set.go (84 lines of code) (raw):
package resources
import (
"math/rand"
"sync"
"time"
)
const (
defaultNumberOfBuckets = 6
defaultBucketDurationInSeconds = 10
)
var defaultTiersValue = [4]int{90, 70, 30, 0}
var defaultTimeProvider = func() int64 { return time.Now().Unix() }
type RankedStorageAccountSet struct {
accounts map[string]*RankedStorageAccount
numberOfBuckets int
bucketDuration int64
tiers []int
timeProvider func() int64
lock sync.Mutex
}
func newRankedStorageAccountSet(
numberOfBuckets int,
bucketDuration int64,
tiers []int,
timeProvider func() int64,
) *RankedStorageAccountSet {
return &RankedStorageAccountSet{
accounts: make(map[string]*RankedStorageAccount),
numberOfBuckets: numberOfBuckets,
bucketDuration: bucketDuration,
tiers: tiers,
timeProvider: timeProvider,
lock: sync.Mutex{},
}
}
func newDefaultRankedStorageAccountSet() *RankedStorageAccountSet {
return newRankedStorageAccountSet(defaultNumberOfBuckets, defaultBucketDurationInSeconds, defaultTiersValue[:], defaultTimeProvider)
}
func (r *RankedStorageAccountSet) addAccountResult(accountName string, success bool) {
r.lock.Lock()
defer r.lock.Unlock()
account, ok := r.accounts[accountName]
if ok {
account.logResult(success)
}
}
func (r *RankedStorageAccountSet) registerStorageAccount(accountName string) {
r.lock.Lock()
defer r.lock.Unlock()
if _, ok := r.accounts[accountName]; !ok {
r.accounts[accountName] = newRankedStorageAccount(accountName, r.numberOfBuckets, r.bucketDuration, r.timeProvider)
}
}
func (r *RankedStorageAccountSet) getStorageAccount(accountName string) (*RankedStorageAccount, bool) {
r.lock.Lock()
defer r.lock.Unlock()
account, ok := r.accounts[accountName]
return account, ok
}
func (r *RankedStorageAccountSet) getRankedShuffledAccounts() []RankedStorageAccount {
r.lock.Lock()
defer r.lock.Unlock()
accountsByTier := make([][]RankedStorageAccount, len(r.tiers))
for i := range accountsByTier {
accountsByTier[i] = []RankedStorageAccount{}
}
for _, account := range r.accounts {
rankPercentage := int(account.getRank() * 100.0)
for i := range r.tiers {
if rankPercentage >= r.tiers[i] {
accountsByTier[i] = append(accountsByTier[i], *account)
break
}
}
}
var result []RankedStorageAccount
for _, tier := range accountsByTier {
rand.Shuffle(len(tier), func(i, j int) {
tier[i], tier[j] = tier[j], tier[i]
})
//Apend to results
result = append(result, tier...)
}
return result
}