diff --git a/pkg/cache/cache.go b/pkg/cache/cache.go index 44ae5cb..041ef21 100644 --- a/pkg/cache/cache.go +++ b/pkg/cache/cache.go @@ -2,6 +2,6 @@ package cache type Cache interface { Get(namespace string) Namespace - Clear(namespace string) + Clear(namespaces ...string) List() map[string]Namespace } diff --git a/pkg/cache/memorycache.go b/pkg/cache/memorycache.go index ca8c860..3086a81 100644 --- a/pkg/cache/memorycache.go +++ b/pkg/cache/memorycache.go @@ -1,32 +1,43 @@ package cache -type MemoryCache map[string]MemoryNamespace +import ( + "sync" +) -func NewMemoryCache() MemoryCache { - return MemoryCache{} +type MemoryCache struct { + store sync.Map } -func (c MemoryCache) Clear(namespace string) { - if namespace == "" { - for _, value := range c { - value.Delete("") - } - } else { - c.Get(namespace).Delete("") +func NewMemoryCache() *MemoryCache { + return &MemoryCache{ + store: sync.Map{}, } } -func (c MemoryCache) Get(namespace string) Namespace { - if _, ok := c[namespace]; !ok { - c[namespace] = MemoryNamespace{} +func (c *MemoryCache) Clear(namespaces ...string) { + if len(namespaces) == 0 { + c.store.Range(func(key, value interface{}) bool { + namespaces = append(namespaces, key.(string)) + return true + }) + } + for _, namespace := range namespaces { + c.Get(namespace).Delete() } - return c[namespace] } -func (c MemoryCache) List() map[string]Namespace { +func (c *MemoryCache) Get(namespace string) Namespace { + value, _ := c.store.LoadOrStore(namespace, &MemoryNamespace{ + store: sync.Map{}, + }) + return value.(*MemoryNamespace) +} + +func (c *MemoryCache) List() map[string]Namespace { ret := map[string]Namespace{} - for s, namespace := range c { - ret[s] = namespace - } + c.store.Range(func(k, v interface{}) bool { + ret[k.(string)] = v.(*MemoryNamespace) + return true + }) return ret } diff --git a/pkg/cache/memorynamespace.go b/pkg/cache/memorynamespace.go index 2faeb02..6c615f3 100644 --- a/pkg/cache/memorynamespace.go +++ b/pkg/cache/memorynamespace.go @@ -1,38 +1,44 @@ package cache -import "github.com/c-bata/go-prompt" +import ( + "sync" -type MemoryNamespace map[string]interface{} + "github.com/c-bata/go-prompt" +) -func (c MemoryNamespace) Delete(key string) { - if key == "" { - for key := range c { - delete(c, key) - } +type MemoryNamespace struct { + store sync.Map +} + +func (c *MemoryNamespace) Delete(keys ...string) { + if len(keys) == 0 { + c.store.Clear() } else { - delete(c, key) - } -} - -func (c MemoryNamespace) Get(key string, cb func() interface{}) interface{} { - if _, ok := c[key]; !ok { - if cb == nil { - return nil + for _, key := range keys { + c.store.Delete(key) } - c[key] = cb() } - return c[key] } -func (c MemoryNamespace) Keys() []string { - keys := make([]string, 0, len(c)) - for k := range c { - keys = append(keys, k) +func (c *MemoryNamespace) Get(key string, cb func() any) any { + value, ok := c.store.Load(key) + if !ok && cb != nil { + value = cb() + c.store.Store(key, value) } + return value +} + +func (c *MemoryNamespace) Keys() []string { + var keys []string + c.store.Range(func(k, v interface{}) bool { + keys = append(keys, k.(string)) + return true + }) return keys } -func (c MemoryNamespace) GetSuggests(key string, cb func() interface{}) []prompt.Suggest { +func (c *MemoryNamespace) GetSuggests(key string, cb func() any) []prompt.Suggest { if v, ok := c.Get(key, cb).([]prompt.Suggest); ok { return v } diff --git a/pkg/cache/namespace.go b/pkg/cache/namespace.go index 9ef6373..6ffb034 100644 --- a/pkg/cache/namespace.go +++ b/pkg/cache/namespace.go @@ -7,6 +7,6 @@ import ( type Namespace interface { Get(key string, cb func() any) any Keys() []string - Delete(key string) + Delete(keys ...string) GetSuggests(key string, cb func() any) []prompt.Suggest } diff --git a/pkg/command/cache.go b/pkg/command/cache.go index 737e038..0ddf793 100644 --- a/pkg/command/cache.go +++ b/pkg/command/cache.go @@ -106,7 +106,7 @@ func (c *Cache) clear(ctx context.Context, r *readline.Readline) error { } } else { c.l.Info("clearing all caches") - c.cache.Clear("") + c.cache.Clear() } return nil }