initial commit

This commit is contained in:
2024-11-08 20:51:12 -05:00
commit 98fa840f87
8 changed files with 739 additions and 0 deletions

15
pkg/cache/cache.go vendored Normal file
View File

@@ -0,0 +1,15 @@
package cache
import "io"
type Cache interface {
Get(key string, writer io.Writer) error
GetString(key string) (string, error)
GetJSON(key string, value any) error
Set(key string, value io.Reader) error
SetJSON(key string, value any) error
SetString(key string, value string) error
Delete(key string) error
}

160
pkg/cache/directory.go vendored Normal file
View File

@@ -0,0 +1,160 @@
package cache
import (
"bytes"
"context"
"encoding/json"
"io"
"os"
"path/filepath"
"sync"
"time"
)
type Directory struct {
BaseFolder string
MaxLife time.Duration
lock sync.Mutex
}
var _ Cache = &Directory{}
func (d *Directory) GetPath(key string) string {
return filepath.Join(d.BaseFolder, key+".json")
}
func (d *Directory) Cleanup(_ context.Context) error {
d.lock.Lock()
defer func() {
d.lock.Unlock()
}()
// go through the BaseFilder looking for any files that are older than MaxLife
return filepath.Walk(d.BaseFolder, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
// ignore directories
if info.IsDir() {
return nil
}
// only files that end in .json
if filepath.Ext(path) != ".json" {
return nil
}
// if the openFile is older than MaxLife, delete it
if time.Since(info.ModTime()) > d.MaxLife {
return os.Remove(path)
}
return nil
})
}
// AutoCleanupRoutine will continually loop and cleanup the directory, until the context is cancelled or an error occurs
// returns nil on context cancellation, or an error if one occurs during cleanup
func (d *Directory) AutoCleanupRoutine(ctx context.Context) error {
for {
select {
case <-ctx.Done():
return nil
case <-time.After(d.MaxLife):
err := d.Cleanup(ctx)
if err != nil {
return err
}
}
}
}
func (d *Directory) openFile(key string) (*os.File, error) {
path := d.GetPath(key)
return os.Open(path)
}
func (d *Directory) Set(key string, value io.Reader) error {
d.lock.Lock()
defer d.lock.Unlock()
fp, err := d.openFile(key)
if err != nil {
return err
}
defer func(fp *os.File) {
_ = fp.Close()
}(fp)
_, err = io.Copy(fp, value)
return err
}
func (d *Directory) SetJSON(key string, value any) error {
d.lock.Lock()
defer d.lock.Unlock()
fp, err := d.openFile(key)
if err != nil {
return err
}
defer func(fp *os.File) {
_ = fp.Close()
}(fp)
return json.NewEncoder(fp).Encode(value)
}
func (d *Directory) SetString(key, value string) error {
return d.Set(key, bytes.NewReader([]byte(value)))
}
func (d *Directory) Get(key string, w io.Writer) error {
d.lock.Lock()
defer d.lock.Unlock()
fp, err := d.openFile(key)
if err != nil {
return err
}
defer fp.Close()
_, err = io.Copy(w, fp)
return err
}
func (d *Directory) GetJSON(key string, v any) error {
d.lock.Lock()
defer d.lock.Unlock()
fp, err := d.openFile(key)
if err != nil {
return err
}
defer fp.Close()
return json.NewEncoder(fp).Encode(v)
}
func (d *Directory) GetString(key string) (string, error) {
var buf bytes.Buffer
err := d.Get(key, &buf)
return buf.String(), err
}
func (d *Directory) Delete(key string) error {
d.lock.Lock()
defer d.lock.Unlock()
return os.Remove(d.GetPath(key))
}