Compare commits

..

No commits in common. "5f766a0efbcb69e8c65291c49acbb206dc2acc6e" and "7b7e8d00586955142ae810a3e14819c0e368ced7" have entirely different histories.

4 changed files with 24 additions and 85 deletions

4
.gitignore vendored
View File

@ -2,5 +2,5 @@
/manager /manager
*.properties *.properties
.DS_Store .DS_Store
/vendor *.csv
.recordsCache /vendor

View File

@ -129,10 +129,16 @@ func main() {
log.Fatalln(err) log.Fatalln(err)
} }
log.Printf("latest migration: %d; migrations run: %d", latest, run) log.Printf("latest migration: %d; migrations run: %d", latest, run)
discogsCache, err := database.NewDiscogsCache(c.DiscogsToken, time.Hour*24, c.DiscogsUser, c.DiscogsPersist, c.DiscogsCacheFile) discogsCache, err := database.NewDiscogsCache(c.DiscogsToken, time.Hour*24, "delta.mu.alpha")
if err != nil { if err != nil {
log.Fatalln(err) log.Fatalln(err)
} }
go func() {
err := discogsCache.FlushCache(context.Background())
if err != nil {
log.Printf("error loading discogs content: %v", err)
}
}()
r := &Router{ r := &Router{
static: f, static: f,
lib: lib, lib: lib,

View File

@ -1,14 +1,11 @@
package config package config
type Config struct { type Config struct {
DBUser string DBUser string
DBPass string DBPass string
DBHost string DBHost string
DBPort string DBPort string
DBName string DBName string
DiscogsToken string DiscogsToken string
DiscogsUser string Debug bool
DiscogsPersist bool
DiscogsCacheFile string `default:".recordsCache"`
Debug bool
} }

View File

@ -2,11 +2,8 @@ package database
import ( import (
"context" "context"
"encoding/gob"
"errors"
"fmt" "fmt"
"log" "log"
"os"
"strconv" "strconv"
"sync" "sync"
"time" "time"
@ -23,16 +20,9 @@ type DiscogsCache struct {
lastRefresh time.Time lastRefresh time.Time
client discogs.Discogs client discogs.Discogs
username string username string
persistence bool
persistFile string
} }
type persistence struct { func NewDiscogsCache(token string, maxCacheAge time.Duration, username string) (*DiscogsCache, error) {
CachedRecordSlice []media.Record
LastRefresh time.Time
}
func NewDiscogsCache(token string, maxCacheAge time.Duration, username string, persist bool, persistFile string) (*DiscogsCache, error) {
client, err := discogs.New(&discogs.Options{ client, err := discogs.New(&discogs.Options{
UserAgent: "library.yetaga.in personal collection cache", UserAgent: "library.yetaga.in personal collection cache",
Token: token, Token: token,
@ -40,52 +30,21 @@ func NewDiscogsCache(token string, maxCacheAge time.Duration, username string, p
if err != nil { if err != nil {
return nil, err return nil, err
} }
cache := &DiscogsCache{ return &DiscogsCache{
authToken: token, authToken: token,
client: client, client: client,
maxCacheAge: maxCacheAge, maxCacheAge: maxCacheAge,
username: username, username: username,
persistence: persist, }, nil
persistFile: persistFile,
}
if cache.persistence && cache.persistFile != "" {
p := &persistence{}
f, err := os.Open(cache.persistFile)
if errors.Is(err, os.ErrNotExist) {
log.Printf("%s not found, skipping file load...", cache.persistFile)
return cache, nil
}
if err != nil {
return cache, fmt.Errorf("error opening cache file %s: %w", cache.persistFile, err)
}
err = gob.NewDecoder(f).Decode(p)
if err != nil {
return cache, fmt.Errorf("error readhing from cache file %s: %w", cache.persistFile, err)
}
log.Printf("loaded %d records from %s", len(p.CachedRecordSlice), cache.persistFile)
cache.cache = p.CachedRecordSlice
cache.lastRefresh = p.LastRefresh
if time.Now().After(cache.lastRefresh.Add(cache.maxCacheAge)) {
log.Printf("cache expired, running refresh...")
go func() {
err := cache.FlushCache(context.Background())
if err != nil {
log.Printf("error loading discogs content: %v", err)
}
}()
}
}
return cache, nil
} }
func (c *DiscogsCache) FlushCache(ctx context.Context) error { func (c *DiscogsCache) FlushCache(ctx context.Context) error {
c.m.Lock() c.m.Lock()
defer c.m.Unlock() defer c.m.Unlock()
records, err := c.fetchRecords(ctx, nil) records, err := c.fetchRecords(ctx, nil)
if err != nil { c.cache = records
return err c.lastRefresh = time.Now()
} return err
return c.saveRecordsToCache(ctx, records)
} }
func (c *DiscogsCache) GetAllRecords(ctx context.Context) ([]media.Record, error) { func (c *DiscogsCache) GetAllRecords(ctx context.Context) ([]media.Record, error) {
@ -93,36 +52,13 @@ func (c *DiscogsCache) GetAllRecords(ctx context.Context) ([]media.Record, error
defer c.m.Unlock() defer c.m.Unlock()
if time.Now().After(c.lastRefresh.Add(c.maxCacheAge)) { if time.Now().After(c.lastRefresh.Add(c.maxCacheAge)) {
records, err := c.fetchRecords(ctx, nil) records, err := c.fetchRecords(ctx, nil)
if err != nil { c.cache = records
return c.cache, err c.lastRefresh = time.Now()
}
err = c.saveRecordsToCache(ctx, records)
return c.cache, err return c.cache, err
} }
return c.cache, nil return c.cache, nil
} }
func (c *DiscogsCache) saveRecordsToCache(ctx context.Context, records []media.Record) error {
c.cache = records
c.lastRefresh = time.Now()
if c.persistence && c.persistFile != "" {
p := persistence{
CachedRecordSlice: c.cache,
LastRefresh: c.lastRefresh,
}
f, err := os.OpenFile(c.persistFile, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755)
if err != nil {
return fmt.Errorf("error opening cache file %s: %w", c.persistFile, err)
}
err = gob.NewEncoder(f).Encode(p)
if err != nil {
return fmt.Errorf("error writing to cache file %s: %w", c.persistFile, err)
}
log.Printf("wrote %d records to %s", len(c.cache), c.persistFile)
}
return nil
}
func (c *DiscogsCache) fetchRecords(ctx context.Context, pagination *discogs.Pagination) ([]media.Record, error) { func (c *DiscogsCache) fetchRecords(ctx context.Context, pagination *discogs.Pagination) ([]media.Record, error) {
records := []media.Record{} records := []media.Record{}
if pagination == nil { if pagination == nil {