From 019ec38fc1288cfebbe45b4ebe434469feaf7543 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20H=C3=A5rek=20Andreassen?= Date: Fri, 4 Oct 2024 21:53:00 +0200 Subject: [PATCH] feat: Add initial caching MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit References: https://todo.sr.ht/~timharek/yr/1 Signed-off-by: Tim HĂ„rek Andreassen --- pkg/cache/cache.go | 69 +++++++++++++++++++++++++++++++++++++++++ pkg/cache/cache_test.go | 27 ++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 pkg/cache/cache.go create mode 100644 pkg/cache/cache_test.go diff --git a/pkg/cache/cache.go b/pkg/cache/cache.go new file mode 100644 index 0000000..0d341a4 --- /dev/null +++ b/pkg/cache/cache.go @@ -0,0 +1,69 @@ +package cache + +import ( + "encoding/json" + "errors" + "fmt" + "io" + "os" + "path/filepath" +) + +type Cache[T any] struct { + Path string +} + +func New[T any](path string) *Cache[T] { + if path == "" { + path = os.TempDir() + } + return &Cache[T]{path} +} + +// Add data as JSON-file into cache-dir, returns nil if success +func (c *Cache[T]) Add(name string, data any) error { + j, err := json.MarshalIndent(data, "", " ") + if err != nil { + return fmt.Errorf("Failed to convert data as JSON.") + } + err = os.MkdirAll(c.Path, 0646) + if err != nil { + return fmt.Errorf("Failed to ensure cache-dir is present.") + } + + filePath := filepath.Join(c.Path, fmt.Sprintf("%s.json", name)) + d := []byte(j) + err = os.WriteFile(filePath, d, 0646) + if err != nil { + return fmt.Errorf("Failed write data to cache-file.") + } + + return nil +} + +// Get data from JSON-file from cache-dir, returns nil if no result +func (c *Cache[T]) Get(name string) (*T, error) { + filePath := filepath.Join(c.Path, fmt.Sprintf("%s.json", name)) + if _, err := os.Stat(filePath); errors.Is(err, os.ErrNotExist) { + return nil, nil + } + + rawFile, err := os.Open(filePath) + if err != nil { + return nil, fmt.Errorf("Failed to read cache-file.") + } + + var result T + + bytes, err := io.ReadAll(rawFile) + if err != nil { + return nil, fmt.Errorf("Failed to read data from cache-file.") + } + + err = json.Unmarshal(bytes, &result) + if err != nil { + return nil, fmt.Errorf("Failed to parse JSON from cache-file.") + } + + return &result, nil +} diff --git a/pkg/cache/cache_test.go b/pkg/cache/cache_test.go new file mode 100644 index 0000000..b9c1e77 --- /dev/null +++ b/pkg/cache/cache_test.go @@ -0,0 +1,27 @@ +package cache + +import ( + "os" + "testing" + + "github.com/stretchr/testify/assert" +) + +type testType struct { + Prop1 string `json:"prop1"` + Prop2 string `json:"prop2"` +} + +func TestCache(t *testing.T) { + assert := assert.New(t) + c := New[testType]("") + assert.Equal(os.TempDir(), c.Path) + + err := c.Add("something", &testType{Prop1: "test1", Prop2: "test2"}) + assert.NoError(err) + + result, err := c.Get("something") + assert.NoError(err) + assert.Equal("test1", result.Prop1) + assert.Equal("test2", result.Prop2) +}