mirror of
https://github.com/hanzoai/metrics.git
synced 2026-10-30 20:03:39 +00:00
Use the same sharded implementation as in metricIDCache. The change is basically a copy-paste. The only difference is that the rotation period remains `1h` instead `1m` in order not to break the fix for #10064. Signed-off-by: Artem Fetishev <[email protected]>
128 lines
3.3 KiB
Go
128 lines
3.3 KiB
Go
//go:build synctest
|
|
|
|
package storage
|
|
|
|
import (
|
|
"testing"
|
|
"testing/synctest"
|
|
"time"
|
|
|
|
"github.com/google/go-cmp/cmp"
|
|
"github.com/google/go-cmp/cmp/cmpopts"
|
|
)
|
|
|
|
func (c *dateMetricIDCache) numShards() uint64 {
|
|
return uint64(len(c.shards))
|
|
}
|
|
|
|
func (c *dateMetricIDCache) fullRotationPeriod() time.Duration {
|
|
return dateMetricIDCacheShardCount * c.rotationPeriod
|
|
}
|
|
|
|
func TestDateMetricIDCache_ClearedWhenUnused(t *testing.T) {
|
|
// Entries that are added to the cache but then never retrieved will be
|
|
// eventually removed from it.
|
|
synctest.Test(t, func(t *testing.T) {
|
|
c := newDateMetricIDCache()
|
|
defer c.MustStop()
|
|
c.Set(123, 456)
|
|
// It takes 3 full rotation cycles for an entry to be evicted from the
|
|
// cache:
|
|
// [in next] -rotation1-> [in curr] -rotation2-> [in prev] -rotation3-> evicted.
|
|
time.Sleep(3 * c.fullRotationPeriod())
|
|
if c.Has(123, 456) {
|
|
t.Fatalf("entry is still in cache")
|
|
}
|
|
})
|
|
|
|
// Entries that are added to the cache and retrieved but then never
|
|
// retrieved again will be eventually removed from it.
|
|
synctest.Test(t, func(t *testing.T) {
|
|
c := newDateMetricIDCache()
|
|
defer c.MustStop()
|
|
c.Set(123, 456)
|
|
time.Sleep(c.fullRotationPeriod())
|
|
if !c.Has(123, 456) {
|
|
t.Fatalf("entry not in cache")
|
|
}
|
|
time.Sleep(3 * c.fullRotationPeriod())
|
|
if c.Has(123, 456) {
|
|
t.Fatalf("entry is still in cache")
|
|
}
|
|
})
|
|
|
|
// Entries that are added to the cache and then periodically retrieved,
|
|
// will remain in cache indefinitely.
|
|
synctest.Test(t, func(t *testing.T) {
|
|
c := newDateMetricIDCache()
|
|
defer c.MustStop()
|
|
c.Set(123, 456)
|
|
for range 10_000 {
|
|
time.Sleep(c.fullRotationPeriod())
|
|
if !c.Has(123, 456) {
|
|
t.Fatalf("entry not in cache")
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestDateMetricIDCache_Stats(t *testing.T) {
|
|
assertStats := func(t *testing.T, c *dateMetricIDCache, want dateMetricIDCacheStats) {
|
|
t.Helper()
|
|
if diff := cmp.Diff(want, c.Stats(), cmpopts.IgnoreFields(dateMetricIDCacheStats{}, "SizeBytes")); diff != "" {
|
|
t.Fatalf("unexpected stats (-want, +got):\n%s", diff)
|
|
}
|
|
}
|
|
|
|
const (
|
|
date = 12345
|
|
numMetricIDs = 16 * 65536
|
|
)
|
|
|
|
synctest.Test(t, func(t *testing.T) {
|
|
c := newDateMetricIDCache()
|
|
defer c.MustStop()
|
|
|
|
// Check stats right after the creation.
|
|
assertStats(t, c, dateMetricIDCacheStats{})
|
|
|
|
// Add metricIDs and check stats.
|
|
// At this point, all metricIDs are in next.
|
|
for metricID := range uint64(numMetricIDs) {
|
|
c.Set(date, metricID)
|
|
}
|
|
assertStats(t, c, dateMetricIDCacheStats{
|
|
Size: numMetricIDs,
|
|
})
|
|
|
|
// Get all metricIDs and check stats.
|
|
// All metricIDs will be sync'ed from next to curr.
|
|
for metricID := range uint64(numMetricIDs) {
|
|
if !c.Has(date, metricID) {
|
|
t.Fatalf("metricID not in cache: %d", metricID)
|
|
}
|
|
}
|
|
assertStats(t, c, dateMetricIDCacheStats{
|
|
Size: numMetricIDs,
|
|
SyncsCount: c.numShards(),
|
|
})
|
|
|
|
// Wait until all groups are rotated.
|
|
// curr metricIDs will be moved to prev.
|
|
time.Sleep(c.fullRotationPeriod() + time.Second)
|
|
assertStats(t, c, dateMetricIDCacheStats{
|
|
Size: numMetricIDs,
|
|
SyncsCount: c.numShards(),
|
|
RotationsCount: c.numShards(),
|
|
})
|
|
|
|
// Wait until all groups are rotated.
|
|
// The cache now should be empty.
|
|
time.Sleep(c.fullRotationPeriod())
|
|
assertStats(t, c, dateMetricIDCacheStats{
|
|
SyncsCount: c.numShards(),
|
|
RotationsCount: 2 * c.numShards(),
|
|
})
|
|
})
|
|
}
|