rely more on generic inference

This commit is contained in:
Karl Seguin
2022-03-03 20:47:12 +08:00
parent 516d62ed5f
commit c4d364ba51
4 changed files with 33 additions and 31 deletions

View File

@@ -11,7 +11,7 @@ import (
) )
func Test_CacheDeletesAValue(t *testing.T) { func Test_CacheDeletesAValue(t *testing.T) {
cache := New[string](Configure[string]()) cache := New(Configure[string]())
defer cache.Stop() defer cache.Stop()
assert.Equal(t, cache.ItemCount(), 0) assert.Equal(t, cache.ItemCount(), 0)
@@ -26,7 +26,7 @@ func Test_CacheDeletesAValue(t *testing.T) {
} }
func Test_CacheDeletesAPrefix(t *testing.T) { func Test_CacheDeletesAPrefix(t *testing.T) {
cache := New[string](Configure[string]()) cache := New(Configure[string]())
defer cache.Stop() defer cache.Stop()
assert.Equal(t, cache.ItemCount(), 0) assert.Equal(t, cache.ItemCount(), 0)
@@ -50,7 +50,7 @@ func Test_CacheDeletesAPrefix(t *testing.T) {
} }
func Test_CacheDeletesAFunc(t *testing.T) { func Test_CacheDeletesAFunc(t *testing.T) {
cache := New[int](Configure[int]()) cache := New(Configure[int]())
defer cache.Stop() defer cache.Stop()
assert.Equal(t, cache.ItemCount(), 0) assert.Equal(t, cache.ItemCount(), 0)
@@ -87,7 +87,7 @@ func Test_CacheOnDeleteCallbackCalled(t *testing.T) {
} }
} }
cache := New[string](Configure[string]().OnDelete(onDeleteFn)) cache := New(Configure[string]().OnDelete(onDeleteFn))
cache.Set("spice", "flow", time.Minute) cache.Set("spice", "flow", time.Minute)
cache.Set("worm", "sand", time.Minute) cache.Set("worm", "sand", time.Minute)
@@ -102,7 +102,7 @@ func Test_CacheOnDeleteCallbackCalled(t *testing.T) {
} }
func Test_CacheFetchesExpiredItems(t *testing.T) { func Test_CacheFetchesExpiredItems(t *testing.T) {
cache := New[string](Configure[string]()) cache := New(Configure[string]())
fn := func() (string, error) { return "moo-moo", nil } fn := func() (string, error) { return "moo-moo", nil }
cache.Set("beef", "moo", time.Second*-1) cache.Set("beef", "moo", time.Second*-1)
@@ -113,7 +113,7 @@ func Test_CacheFetchesExpiredItems(t *testing.T) {
} }
func Test_CacheGCsTheOldestItems(t *testing.T) { func Test_CacheGCsTheOldestItems(t *testing.T) {
cache := New[int](Configure[int]().ItemsToPrune(10)) cache := New(Configure[int]().ItemsToPrune(10))
for i := 0; i < 500; i++ { for i := 0; i < 500; i++ {
cache.Set(strconv.Itoa(i), i, time.Minute) cache.Set(strconv.Itoa(i), i, time.Minute)
} }
@@ -125,7 +125,7 @@ func Test_CacheGCsTheOldestItems(t *testing.T) {
} }
func Test_CachePromotedItemsDontGetPruned(t *testing.T) { func Test_CachePromotedItemsDontGetPruned(t *testing.T) {
cache := New[int](Configure[int]().ItemsToPrune(10).GetsPerPromote(1)) cache := New(Configure[int]().ItemsToPrune(10).GetsPerPromote(1))
for i := 0; i < 500; i++ { for i := 0; i < 500; i++ {
cache.Set(strconv.Itoa(i), i, time.Minute) cache.Set(strconv.Itoa(i), i, time.Minute)
} }
@@ -139,7 +139,7 @@ func Test_CachePromotedItemsDontGetPruned(t *testing.T) {
} }
func Test_CacheTrackerDoesNotCleanupHeldInstance(t *testing.T) { func Test_CacheTrackerDoesNotCleanupHeldInstance(t *testing.T) {
cache := New[int](Configure[int]().ItemsToPrune(11).Track()) cache := New(Configure[int]().ItemsToPrune(11).Track())
item0 := cache.TrackingSet("0", 0, time.Minute) item0 := cache.TrackingSet("0", 0, time.Minute)
for i := 1; i < 11; i++ { for i := 1; i < 11; i++ {
cache.Set(strconv.Itoa(i), i, time.Minute) cache.Set(strconv.Itoa(i), i, time.Minute)
@@ -164,7 +164,7 @@ func Test_CacheRemovesOldestItemWhenFull(t *testing.T) {
} }
} }
cache := New[int](Configure[int]().MaxSize(5).ItemsToPrune(1).OnDelete(onDeleteFn)) cache := New(Configure[int]().MaxSize(5).ItemsToPrune(1).OnDelete(onDeleteFn))
for i := 0; i < 7; i++ { for i := 0; i < 7; i++ {
cache.Set(strconv.Itoa(i), i, time.Minute) cache.Set(strconv.Itoa(i), i, time.Minute)
} }
@@ -177,7 +177,7 @@ func Test_CacheRemovesOldestItemWhenFull(t *testing.T) {
} }
func Test_CacheRemovesOldestItemWhenFullBySizer(t *testing.T) { func Test_CacheRemovesOldestItemWhenFullBySizer(t *testing.T) {
cache := New[*SizedItem](Configure[*SizedItem]().MaxSize(9).ItemsToPrune(2)) cache := New(Configure[*SizedItem]().MaxSize(9).ItemsToPrune(2))
for i := 0; i < 7; i++ { for i := 0; i < 7; i++ {
cache.Set(strconv.Itoa(i), &SizedItem{i, 2}, time.Minute) cache.Set(strconv.Itoa(i), &SizedItem{i, 2}, time.Minute)
} }
@@ -192,7 +192,7 @@ func Test_CacheRemovesOldestItemWhenFullBySizer(t *testing.T) {
} }
func Test_CacheSetUpdatesSizeOnDelta(t *testing.T) { func Test_CacheSetUpdatesSizeOnDelta(t *testing.T) {
cache := New[*SizedItem](Configure[*SizedItem]()) cache := New(Configure[*SizedItem]())
cache.Set("a", &SizedItem{0, 2}, time.Minute) cache.Set("a", &SizedItem{0, 2}, time.Minute)
cache.Set("b", &SizedItem{0, 3}, time.Minute) cache.Set("b", &SizedItem{0, 3}, time.Minute)
cache.SyncUpdates() cache.SyncUpdates()
@@ -212,7 +212,7 @@ func Test_CacheSetUpdatesSizeOnDelta(t *testing.T) {
} }
func Test_CacheReplaceDoesNotchangeSizeIfNotSet(t *testing.T) { func Test_CacheReplaceDoesNotchangeSizeIfNotSet(t *testing.T) {
cache := New[*SizedItem](Configure[*SizedItem]()) cache := New(Configure[*SizedItem]())
cache.Set("1", &SizedItem{1, 2}, time.Minute) cache.Set("1", &SizedItem{1, 2}, time.Minute)
cache.Set("2", &SizedItem{1, 2}, time.Minute) cache.Set("2", &SizedItem{1, 2}, time.Minute)
cache.Set("3", &SizedItem{1, 2}, time.Minute) cache.Set("3", &SizedItem{1, 2}, time.Minute)
@@ -222,7 +222,7 @@ func Test_CacheReplaceDoesNotchangeSizeIfNotSet(t *testing.T) {
} }
func Test_CacheReplaceChangesSize(t *testing.T) { func Test_CacheReplaceChangesSize(t *testing.T) {
cache := New[*SizedItem](Configure[*SizedItem]()) cache := New(Configure[*SizedItem]())
cache.Set("1", &SizedItem{1, 2}, time.Minute) cache.Set("1", &SizedItem{1, 2}, time.Minute)
cache.Set("2", &SizedItem{1, 2}, time.Minute) cache.Set("2", &SizedItem{1, 2}, time.Minute)
@@ -240,7 +240,7 @@ func Test_CacheReplaceChangesSize(t *testing.T) {
} }
func Test_CacheResizeOnTheFly(t *testing.T) { func Test_CacheResizeOnTheFly(t *testing.T) {
cache := New[int](Configure[int]().MaxSize(9).ItemsToPrune(1)) cache := New(Configure[int]().MaxSize(9).ItemsToPrune(1))
for i := 0; i < 5; i++ { for i := 0; i < 5; i++ {
cache.Set(strconv.Itoa(i), i, time.Minute) cache.Set(strconv.Itoa(i), i, time.Minute)
} }
@@ -272,7 +272,7 @@ func Test_CacheResizeOnTheFly(t *testing.T) {
} }
func Test_CacheForEachFunc(t *testing.T) { func Test_CacheForEachFunc(t *testing.T) {
cache := New[int](Configure[int]().MaxSize(3).ItemsToPrune(1)) cache := New(Configure[int]().MaxSize(3).ItemsToPrune(1))
assert.List(t, forEachKeys[int](cache), []string{}) assert.List(t, forEachKeys[int](cache), []string{})
cache.Set("1", 1, time.Minute) cache.Set("1", 1, time.Minute)

View File

@@ -158,7 +158,7 @@ func Test_LayedCache_DeletesALayer(t *testing.T) {
} }
func Test_LayeredCache_GCsTheOldestItems(t *testing.T) { func Test_LayeredCache_GCsTheOldestItems(t *testing.T) {
cache := Layered[int](Configure[int]().ItemsToPrune(10)) cache := Layered(Configure[int]().ItemsToPrune(10))
cache.Set("xx", "a", 23, time.Minute) cache.Set("xx", "a", 23, time.Minute)
for i := 0; i < 500; i++ { for i := 0; i < 500; i++ {
cache.Set(strconv.Itoa(i), "a", i, time.Minute) cache.Set(strconv.Itoa(i), "a", i, time.Minute)
@@ -175,7 +175,7 @@ func Test_LayeredCache_GCsTheOldestItems(t *testing.T) {
} }
func Test_LayeredCache_PromotedItemsDontGetPruned(t *testing.T) { func Test_LayeredCache_PromotedItemsDontGetPruned(t *testing.T) {
cache := Layered[int](Configure[int]().ItemsToPrune(10).GetsPerPromote(1)) cache := Layered(Configure[int]().ItemsToPrune(10).GetsPerPromote(1))
for i := 0; i < 500; i++ { for i := 0; i < 500; i++ {
cache.Set(strconv.Itoa(i), "a", i, time.Minute) cache.Set(strconv.Itoa(i), "a", i, time.Minute)
} }
@@ -189,7 +189,7 @@ func Test_LayeredCache_PromotedItemsDontGetPruned(t *testing.T) {
} }
func Test_LayeredCache_TrackerDoesNotCleanupHeldInstance(t *testing.T) { func Test_LayeredCache_TrackerDoesNotCleanupHeldInstance(t *testing.T) {
cache := Layered[int](Configure[int]().ItemsToPrune(10).Track()) cache := Layered(Configure[int]().ItemsToPrune(10).Track())
item0 := cache.TrackingSet("0", "a", 0, time.Minute) item0 := cache.TrackingSet("0", "a", 0, time.Minute)
for i := 1; i < 11; i++ { for i := 1; i < 11; i++ {
cache.Set(strconv.Itoa(i), "a", i, time.Minute) cache.Set(strconv.Itoa(i), "a", i, time.Minute)
@@ -207,7 +207,7 @@ func Test_LayeredCache_TrackerDoesNotCleanupHeldInstance(t *testing.T) {
} }
func Test_LayeredCache_RemovesOldestItemWhenFull(t *testing.T) { func Test_LayeredCache_RemovesOldestItemWhenFull(t *testing.T) {
cache := Layered[int](Configure[int]().MaxSize(5).ItemsToPrune(1)) cache := Layered(Configure[int]().MaxSize(5).ItemsToPrune(1))
cache.Set("xx", "a", 23, time.Minute) cache.Set("xx", "a", 23, time.Minute)
for i := 0; i < 7; i++ { for i := 0; i < 7; i++ {
cache.Set(strconv.Itoa(i), "a", i, time.Minute) cache.Set(strconv.Itoa(i), "a", i, time.Minute)
@@ -225,7 +225,7 @@ func Test_LayeredCache_RemovesOldestItemWhenFull(t *testing.T) {
} }
func Test_LayeredCache_ResizeOnTheFly(t *testing.T) { func Test_LayeredCache_ResizeOnTheFly(t *testing.T) {
cache := Layered[int](Configure[int]().MaxSize(9).ItemsToPrune(1)) cache := Layered(Configure[int]().MaxSize(9).ItemsToPrune(1))
for i := 0; i < 5; i++ { for i := 0; i < 5; i++ {
cache.Set(strconv.Itoa(i), "a", i, time.Minute) cache.Set(strconv.Itoa(i), "a", i, time.Minute)
} }
@@ -259,7 +259,7 @@ func Test_LayeredCache_ResizeOnTheFly(t *testing.T) {
} }
func Test_LayeredCache_RemovesOldestItemWhenFullBySizer(t *testing.T) { func Test_LayeredCache_RemovesOldestItemWhenFullBySizer(t *testing.T) {
cache := Layered[*SizedItem](Configure[*SizedItem]().MaxSize(9).ItemsToPrune(2)) cache := Layered(Configure[*SizedItem]().MaxSize(9).ItemsToPrune(2))
for i := 0; i < 7; i++ { for i := 0; i < 7; i++ {
cache.Set("pri", strconv.Itoa(i), &SizedItem{i, 2}, time.Minute) cache.Set("pri", strconv.Itoa(i), &SizedItem{i, 2}, time.Minute)
} }
@@ -272,7 +272,7 @@ func Test_LayeredCache_RemovesOldestItemWhenFullBySizer(t *testing.T) {
} }
func Test_LayeredCache_SetUpdatesSizeOnDelta(t *testing.T) { func Test_LayeredCache_SetUpdatesSizeOnDelta(t *testing.T) {
cache := Layered[*SizedItem](Configure[*SizedItem]()) cache := Layered(Configure[*SizedItem]())
cache.Set("pri", "a", &SizedItem{0, 2}, time.Minute) cache.Set("pri", "a", &SizedItem{0, 2}, time.Minute)
cache.Set("pri", "b", &SizedItem{0, 3}, time.Minute) cache.Set("pri", "b", &SizedItem{0, 3}, time.Minute)
cache.SyncUpdates() cache.SyncUpdates()
@@ -293,7 +293,7 @@ func Test_LayeredCache_SetUpdatesSizeOnDelta(t *testing.T) {
} }
func Test_LayeredCache_ReplaceDoesNotchangeSizeIfNotSet(t *testing.T) { func Test_LayeredCache_ReplaceDoesNotchangeSizeIfNotSet(t *testing.T) {
cache := Layered[*SizedItem](Configure[*SizedItem]()) cache := Layered(Configure[*SizedItem]())
cache.Set("pri", "1", &SizedItem{1, 2}, time.Minute) cache.Set("pri", "1", &SizedItem{1, 2}, time.Minute)
cache.Set("pri", "2", &SizedItem{1, 2}, time.Minute) cache.Set("pri", "2", &SizedItem{1, 2}, time.Minute)
cache.Set("pri", "3", &SizedItem{1, 2}, time.Minute) cache.Set("pri", "3", &SizedItem{1, 2}, time.Minute)
@@ -303,7 +303,7 @@ func Test_LayeredCache_ReplaceDoesNotchangeSizeIfNotSet(t *testing.T) {
} }
func Test_LayeredCache_ReplaceChangesSize(t *testing.T) { func Test_LayeredCache_ReplaceChangesSize(t *testing.T) {
cache := Layered[*SizedItem](Configure[*SizedItem]()) cache := Layered(Configure[*SizedItem]())
cache.Set("pri", "1", &SizedItem{1, 2}, time.Minute) cache.Set("pri", "1", &SizedItem{1, 2}, time.Minute)
cache.Set("pri", "2", &SizedItem{1, 2}, time.Minute) cache.Set("pri", "2", &SizedItem{1, 2}, time.Minute)
@@ -321,7 +321,7 @@ func Test_LayeredCache_ReplaceChangesSize(t *testing.T) {
} }
func Test_LayeredCache_EachFunc(t *testing.T) { func Test_LayeredCache_EachFunc(t *testing.T) {
cache := Layered[int](Configure[int]().MaxSize(3).ItemsToPrune(1)) cache := Layered(Configure[int]().MaxSize(3).ItemsToPrune(1))
assert.List(t, forEachKeysLayered[int](cache, "1"), []string{}) assert.List(t, forEachKeysLayered[int](cache, "1"), []string{})
cache.Set("1", "a", 1, time.Minute) cache.Set("1", "a", 1, time.Minute)

View File

@@ -22,13 +22,15 @@ import (
"github.com/karlseguin/ccache/v3" "github.com/karlseguin/ccache/v3"
) )
var cache = ccache.New[string](ccache.Configure[string]()) // create a cache with string values
var cache = ccache.New(ccache.Configure[string]())
``` ```
`Configure` exposes a chainable API: `Configure` exposes a chainable API:
```go ```go
var cache = ccache.New[int](ccache.Configure[int]().MaxSize(1000).ItemsToPrune(100)) // creates a cache with int values
var cache = ccache.New(ccache.Configure[int]().MaxSize(1000).ItemsToPrune(100))
``` ```
The most likely configuration options to tweak are: The most likely configuration options to tweak are:
@@ -133,7 +135,7 @@ CCache supports a special tracking mode which is meant to be used in conjunction
When you configure your cache with `Track()`: When you configure your cache with `Track()`:
```go ```go
cache = ccache.New(ccache.Configure().Track()) cache = ccache.New(ccache.Configure[int]().Track())
``` ```
The items retrieved via `TrackingGet` will not be eligible for purge until `Release` is called on them: The items retrieved via `TrackingGet` will not be eligible for purge until `Release` is called on them:
@@ -159,7 +161,7 @@ CCache's `LayeredCache` stores and retrieves values by both a primary and second
`LayeredCache` takes the same configuration object as the main cache, exposes the same optional tracking capabilities, but exposes a slightly different API: `LayeredCache` takes the same configuration object as the main cache, exposes the same optional tracking capabilities, but exposes a slightly different API:
```go ```go
cache := ccache.Layered[string](ccache.Configure[string]()) cache := ccache.Layered(ccache.Configure[string]())
cache.Set("/users/goku", "type:json", "{value_to_cache}", time.Minute * 5) cache.Set("/users/goku", "type:json", "{value_to_cache}", time.Minute * 5)
cache.Set("/users/goku", "type:xml", "<value_to_cache>", time.Minute * 5) cache.Set("/users/goku", "type:xml", "<value_to_cache>", time.Minute * 5)
@@ -178,7 +180,7 @@ cache.DeleteAll("/users/goku")
In some cases, when using a `LayeredCache`, it may be desirable to always be acting on the secondary portion of the cache entry. This could be the case where the primary key is used as a key elsewhere in your code. The `SecondaryCache` is retrieved with: In some cases, when using a `LayeredCache`, it may be desirable to always be acting on the secondary portion of the cache entry. This could be the case where the primary key is used as a key elsewhere in your code. The `SecondaryCache` is retrieved with:
```go ```go
cache := ccache.Layered[string](ccache.Configure[string]()) cache := ccache.Layered(ccache.Configure[string]())
sCache := cache.GetOrCreateSecondaryCache("/users/goku") sCache := cache.GetOrCreateSecondaryCache("/users/goku")
sCache.Set("type:json", "{value_to_cache}", time.Minute * 5) sCache.Set("type:json", "{value_to_cache}", time.Minute * 5)
``` ```

View File

@@ -84,7 +84,7 @@ func Test_SecondaryCache_FetchReturnsANewValue(t *testing.T) {
} }
func Test_SecondaryCache_TrackerDoesNotCleanupHeldInstance(t *testing.T) { func Test_SecondaryCache_TrackerDoesNotCleanupHeldInstance(t *testing.T) {
cache := Layered[int](Configure[int]().ItemsToPrune(10).Track()) cache := Layered(Configure[int]().ItemsToPrune(10).Track())
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
cache.Set(strconv.Itoa(i), "a", i, time.Minute) cache.Set(strconv.Itoa(i), "a", i, time.Minute)
} }