scale refresh rate by last calculation time

This commit is contained in:
Samir Patel 2021-06-10 16:30:22 -05:00
parent a7c24c6745
commit 9b11ded9e3

55
api.go
View file

@ -903,10 +903,12 @@ func (api *API) PrimaryNode() *topology.Node {
// Cache of disk usage statistics
type usageCache struct {
data map[string]NodeUsage
refreshInterval time.Duration
lastUpdated time.Time
resetTrigger chan bool
data map[string]NodeUsage
refreshInterval time.Duration
lastUpdated time.Time
resetTrigger chan bool
lastCalcDuration time.Duration
waitMultiplier time.Duration
muCalculate sync.Mutex
muAssign sync.Mutex
@ -955,22 +957,17 @@ func (api *API) Usage(ctx context.Context, remote bool) (map[string]NodeUsage, e
span, _ := tracing.StartSpanFromContext(ctx, "API.Usage")
defer span.Finish()
api.usageCache.muAssign.Lock()
lastUpdated := api.usageCache.lastUpdated
cacheN := len(api.usageCache.data[api.server.nodeID].Disk.IndexUsage)
api.usageCache.muAssign.Unlock()
holderN := len(api.holder.Indexes())
// reset cache if server was started with no data, and data has subsequently been added
if cacheN == 0 && holderN > 0 {
if api.usageCache.lastCalcDuration < (time.Second * 5) {
err := api.ResetUsageCache()
if err != nil {
api.server.logger.Infof("data detected but could not recalculate cache: %s", err)
}
}
var t time.Time
if lastUpdated == t {
api.usageCache.muAssign.Lock()
lastUpdated := api.usageCache.lastUpdated
api.usageCache.muAssign.Unlock()
if lastUpdated == (time.Time{}) {
api.calculateUsage()
}
@ -978,15 +975,6 @@ func (api *API) Usage(ctx context.Context, remote bool) (map[string]NodeUsage, e
api.requestUsageOfNodes()
}
// triggers recalculation of cache in background, ahead of schedule, if number of indexes in
// cache differs from number of indexes in holder
if cacheN > 0 && cacheN != holderN {
err := api.ResetUsageCache()
if err != nil {
api.server.logger.Infof("resetting cache in background: %s", err)
}
}
return api.usageCache.data, nil
}
@ -1077,12 +1065,16 @@ func (api *API) RefreshUsageCache(refresh time.Duration) {
trigger := make(chan bool)
defer close(trigger)
api.usageCache = &usageCache{
data: make(map[string]NodeUsage),
refreshInterval: refresh,
resetTrigger: trigger,
data: make(map[string]NodeUsage),
refreshInterval: refresh,
resetTrigger: trigger,
lastCalcDuration: 0,
waitMultiplier: time.Duration(5),
}
for {
start := time.Now()
api.calculateUsage()
api.setRefreshInterval(time.Since(start))
select {
case <-trigger:
continue
@ -1094,6 +1086,17 @@ func (api *API) RefreshUsageCache(refresh time.Duration) {
}
}
func (api *API) setRefreshInterval(dur time.Duration) {
refresh := dur * api.usageCache.waitMultiplier
if refresh < time.Hour {
refresh = time.Hour
}
api.usageCache.muAssign.Lock()
api.usageCache.refreshInterval = refresh
api.usageCache.lastCalcDuration = dur
api.usageCache.muAssign.Unlock()
}
// Resets the lastUpdated time and awakens RefreshUsageCache()
func (api *API) ResetUsageCache() error {
if api.usageCache != nil {