From 450136a0c0dbd675a87d6af54f7aba5c9d079c21 Mon Sep 17 00:00:00 2001 From: Brian Picciano Date: Sat, 7 May 2022 18:22:57 -0600 Subject: Implement cachedAssetStore --- srv/src/post/asset.go | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) (limited to 'srv/src/post/asset.go') diff --git a/srv/src/post/asset.go b/srv/src/post/asset.go index 3e6ae28..18af8f6 100644 --- a/srv/src/post/asset.go +++ b/srv/src/post/asset.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "io" + "sync" ) var ( @@ -84,3 +85,69 @@ func (s *assetStore) Delete(id string) error { _, err := s.db.Exec(`DELETE FROM assets WHERE id = ?`, id) return err } + +//////////////////////////////////////////////////////////////////////////////// + +type cachedAssetStore struct { + inner AssetStore + m sync.Map +} + +// NewCachedAssetStore wraps an AssetStore in an in-memory cache. +func NewCachedAssetStore(assetStore AssetStore) AssetStore { + return &cachedAssetStore{ + inner: assetStore, + } +} + +func (s *cachedAssetStore) Set(id string, from io.Reader) error { + + buf := new(bytes.Buffer) + from = io.TeeReader(from, buf) + + if err := s.inner.Set(id, from); err != nil { + return err + } + + s.m.Store(id, buf.Bytes()) + return nil +} + +func (s *cachedAssetStore) Get(id string, into io.Writer) error { + + if bodyI, ok := s.m.Load(id); ok { + + if err, ok := bodyI.(error); ok { + return err + } + + if _, err := io.Copy(into, bytes.NewReader(bodyI.([]byte))); err != nil { + return fmt.Errorf("writing body to io.Writer: %w", err) + } + + return nil + } + + buf := new(bytes.Buffer) + into = io.MultiWriter(into, buf) + + if err := s.inner.Get(id, into); errors.Is(err, ErrAssetNotFound) { + s.m.Store(id, err) + return err + } else if err != nil { + return err + } + + s.m.Store(id, buf.Bytes()) + return nil +} + +func (s *cachedAssetStore) Delete(id string) error { + + if err := s.inner.Delete(id); err != nil { + return err + } + + s.m.Delete(id) + return nil +} -- cgit v1.2.3