Compare commits
3 commits
ax/review-
...
dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5eb611f5e2 | ||
|
|
19232c5575 | ||
|
|
248f542b08 |
5 changed files with 70 additions and 5 deletions
34
cache.go
34
cache.go
|
|
@ -166,12 +166,12 @@ func (c *Cache) Set(key string, data any) error {
|
||||||
ExpiresAt: time.Now().Add(ttl),
|
ExpiresAt: time.Now().Add(ttl),
|
||||||
}
|
}
|
||||||
|
|
||||||
entryResult := core.JSONMarshal(entry)
|
entryBytes, err := json.MarshalIndent(entry, "", " ")
|
||||||
if !entryResult.OK {
|
if err != nil {
|
||||||
return core.E("cache.Set", "failed to marshal cache entry", entryResult.Value.(error))
|
return core.E("cache.Set", "failed to marshal cache entry", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := c.medium.Write(path, string(entryResult.Value.([]byte))); err != nil {
|
if err := c.medium.Write(path, string(entryBytes)); err != nil {
|
||||||
return core.E("cache.Set", "failed to write cache file", err)
|
return core.E("cache.Set", "failed to write cache file", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -200,6 +200,32 @@ func (c *Cache) Delete(key string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeleteMany removes several cached items in one call.
|
||||||
|
//
|
||||||
|
// err := c.DeleteMany("github/acme/repos", "github/acme/meta")
|
||||||
|
func (c *Cache) DeleteMany(keys ...string) error {
|
||||||
|
if err := c.ensureReady("cache.DeleteMany"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, key := range keys {
|
||||||
|
path, err := c.Path(key)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = c.medium.Delete(path)
|
||||||
|
if core.Is(err, fs.ErrNotExist) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return core.E("cache.DeleteMany", "failed to delete cache file", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Clear removes all cached items under the cache base directory.
|
// Clear removes all cached items under the cache base directory.
|
||||||
//
|
//
|
||||||
// err := c.Clear()
|
// err := c.Clear()
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
package cache_test
|
package cache_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
|
@ -60,6 +61,9 @@ func TestCache_New_Good(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Read failed: %v", err)
|
t.Fatalf("Read failed: %v", err)
|
||||||
}
|
}
|
||||||
|
if !strings.Contains(raw, "\n \"data\":") {
|
||||||
|
t.Fatalf("expected pretty-printed cache entry, got %q", raw)
|
||||||
|
}
|
||||||
|
|
||||||
entry := readEntry(t, raw)
|
entry := readEntry(t, raw)
|
||||||
ttl := entry.ExpiresAt.Sub(entry.CachedAt)
|
ttl := entry.ExpiresAt.Sub(entry.CachedAt)
|
||||||
|
|
@ -231,6 +235,38 @@ func TestCache_Delete_Good(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCache_DeleteMany_Good(t *testing.T) {
|
||||||
|
c, _ := newTestCache(t, "/tmp/cache-delete-many", time.Minute)
|
||||||
|
data := map[string]string{"foo": "bar"}
|
||||||
|
|
||||||
|
if err := c.Set("key1", data); err != nil {
|
||||||
|
t.Fatalf("Set failed for key1: %v", err)
|
||||||
|
}
|
||||||
|
if err := c.Set("key2", data); err != nil {
|
||||||
|
t.Fatalf("Set failed for key2: %v", err)
|
||||||
|
}
|
||||||
|
if err := c.DeleteMany("key1", "missing", "key2"); err != nil {
|
||||||
|
t.Fatalf("DeleteMany failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var retrieved map[string]string
|
||||||
|
found, err := c.Get("key1", &retrieved)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Get after DeleteMany returned an unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if found {
|
||||||
|
t.Error("expected key1 to be deleted")
|
||||||
|
}
|
||||||
|
|
||||||
|
found, err = c.Get("key2", &retrieved)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Get after DeleteMany returned an unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if found {
|
||||||
|
t.Error("expected key2 to be deleted")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestCache_Clear_Good(t *testing.T) {
|
func TestCache_Clear_Good(t *testing.T) {
|
||||||
c, _ := newTestCache(t, "/tmp/cache-clear", time.Minute)
|
c, _ := newTestCache(t, "/tmp/cache-clear", time.Minute)
|
||||||
data := map[string]string{"foo": "bar"}
|
data := map[string]string{"foo": "bar"}
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ own usage example in a doc comment or Go example test.
|
||||||
| `(*Cache).Get` | `func (c *Cache) Get(key string, dest any) (bool, error)` | `dappco.re/go/core/cache` | Retrieves a cached item if it exists and has not expired. | yes | no |
|
| `(*Cache).Get` | `func (c *Cache) Get(key string, dest any) (bool, error)` | `dappco.re/go/core/cache` | Retrieves a cached item if it exists and has not expired. | yes | no |
|
||||||
| `(*Cache).Set` | `func (c *Cache) Set(key string, data any) error` | `dappco.re/go/core/cache` | Stores an item in the cache. | yes | no |
|
| `(*Cache).Set` | `func (c *Cache) Set(key string, data any) error` | `dappco.re/go/core/cache` | Stores an item in the cache. | yes | no |
|
||||||
| `(*Cache).Delete` | `func (c *Cache) Delete(key string) error` | `dappco.re/go/core/cache` | Removes an item from the cache. | yes | no |
|
| `(*Cache).Delete` | `func (c *Cache) Delete(key string) error` | `dappco.re/go/core/cache` | Removes an item from the cache. | yes | no |
|
||||||
|
| `(*Cache).DeleteMany` | `func (c *Cache) DeleteMany(keys ...string) error` | `dappco.re/go/core/cache` | Removes several items from the cache in one call. | yes | no |
|
||||||
| `(*Cache).Clear` | `func (c *Cache) Clear() error` | `dappco.re/go/core/cache` | Removes all cached items. | yes | no |
|
| `(*Cache).Clear` | `func (c *Cache) Clear() error` | `dappco.re/go/core/cache` | Removes all cached items. | yes | no |
|
||||||
| `(*Cache).Age` | `func (c *Cache) Age(key string) time.Duration` | `dappco.re/go/core/cache` | Returns how old a cached item is, or `-1` if it is not cached. | yes | no |
|
| `(*Cache).Age` | `func (c *Cache) Age(key string) time.Duration` | `dappco.re/go/core/cache` | Returns how old a cached item is, or `-1` if it is not cached. | yes | no |
|
||||||
| `GitHubReposKey` | `func GitHubReposKey(org string) string` | `dappco.re/go/core/cache` | Returns the cache key for an organization's repo list. | yes | no |
|
| `GitHubReposKey` | `func GitHubReposKey(org string) string` | `dappco.re/go/core/cache` | Returns the cache key for an organization's repo list. | yes | no |
|
||||||
|
|
|
||||||
|
|
@ -136,6 +136,8 @@ Key behaviours:
|
||||||
|
|
||||||
- **`Delete(key)`** removes a single entry. If the file does not exist, the
|
- **`Delete(key)`** removes a single entry. If the file does not exist, the
|
||||||
operation succeeds silently.
|
operation succeeds silently.
|
||||||
|
- **`DeleteMany(keys...)`** removes several entries in one call and ignores
|
||||||
|
missing files, using the same per-key path validation as `Delete()`.
|
||||||
- **`Clear()`** calls `medium.DeleteAll(baseDir)`, removing the entire cache
|
- **`Clear()`** calls `medium.DeleteAll(baseDir)`, removing the entire cache
|
||||||
directory and all its contents.
|
directory and all its contents.
|
||||||
|
|
||||||
|
|
|
||||||
2
go.mod
2
go.mod
|
|
@ -7,4 +7,4 @@ require (
|
||||||
dappco.re/go/core/io v0.2.0
|
dappco.re/go/core/io v0.2.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require forge.lthn.ai/core/go-log v0.0.4 // indirect
|
require dappco.re/go/core/log v0.0.4 // indirect
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue