package cache import ( "encoding/json" "errors" "fmt" "io" "os" "path/filepath" "time" ) 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 } // Returns if t is expired func IsExpired(expire time.Time, now *time.Time) bool { if now == nil { tmp := time.Now() now = &tmp } return now.Unix() >= expire.Unix() }