diff options
author | René 'Necoro' Neumann <necoro@necoro.eu> | 2020-04-24 00:22:19 +0200 |
---|---|---|
committer | René 'Necoro' Neumann <necoro@necoro.eu> | 2020-04-24 00:22:19 +0200 |
commit | c08aff21cd67cc27926a4cb1ca72ffe67e015ebf (patch) | |
tree | c9b0185424e0e74bc092a2606c6164c4e6698e48 /internal/cache | |
parent | 8467dbb9bd9960191f16def3ba43dcbde0fdda14 (diff) | |
download | feed2imap-go-c08aff21cd67cc27926a4cb1ca72ffe67e015ebf.tar.gz feed2imap-go-c08aff21cd67cc27926a4cb1ca72ffe67e015ebf.tar.bz2 feed2imap-go-c08aff21cd67cc27926a4cb1ca72ffe67e015ebf.zip |
Started caching
Diffstat (limited to '')
-rw-r--r-- | internal/cache/cache.go | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/internal/cache/cache.go b/internal/cache/cache.go new file mode 100644 index 0000000..979d661 --- /dev/null +++ b/internal/cache/cache.go @@ -0,0 +1,120 @@ +package cache + +import ( + "bufio" + "encoding/gob" + "errors" + "fmt" + "os" + + "github.com/Necoro/feed2imap-go/internal/log" +) + +const currentVersion byte = 1 + +type Cache interface { + Version() byte + transformToCurrent() (Cache, error) +} + +type feedId struct { + Name string + Url string +} + +type v1Cache struct { + version byte + Ids map[feedId]uint64 + NextId uint64 +} + +func (cache *v1Cache) Version() byte { + return cache.version +} + +func New() Cache { + cache := v1Cache{Ids: map[feedId]uint64{}} + cache.version = currentVersion + return &cache +} + +func cacheForVersion(version byte) (Cache, error) { + switch version { + case 1: + return New(), nil + default: + return nil, fmt.Errorf("unknown cache version '%d'", version) + } +} + +func (cache *v1Cache) transformToCurrent() (Cache, error) { + return cache, nil +} + +func Store(fileName string, cache Cache) error { + if cache == nil { + return fmt.Errorf("trying to store nil cache") + } + if cache.Version() != currentVersion { + return fmt.Errorf("trying to store cache with unsupported version '%d' (current: '%d')", cache.Version(), currentVersion) + } + + f, err := os.Create(fileName) + if err != nil { + return fmt.Errorf("trying to store cache to '%s': %w", fileName, err) + } + defer f.Close() + + writer := bufio.NewWriter(f) + if err = writer.WriteByte(currentVersion); err != nil { + return fmt.Errorf("writing to '%s': %w", fileName, err) + } + + encoder := gob.NewEncoder(writer) + if err = encoder.Encode(cache); err != nil { + return fmt.Errorf("encoding cache: %w", err) + } + + writer.Flush() + log.Printf("Stored cache to '%s'.", fileName) + + return nil +} + +func Read(fileName string) (Cache, error) { + f, err := os.Open(fileName) + if err != nil { + if errors.Is(err, os.ErrNotExist) { + // no cache there yet -- make new + return New(), nil + } + return nil, fmt.Errorf("opening cache at '%s': %w", fileName, err) + } + defer f.Close() + + log.Printf("Loading cache from '%s'", fileName) + + reader := bufio.NewReader(f) + version, err := reader.ReadByte() + if err != nil { + return nil, fmt.Errorf("reading from '%s': %w", fileName, err) + } + + cache, err := cacheForVersion(version) + if err != nil { + return nil, err + } + + decoder := gob.NewDecoder(reader) + if err = decoder.Decode(cache); err != nil { + return nil, fmt.Errorf("decoding for version '%d' from '%s': %w", version, fileName, err) + } + + if cache, err = cache.transformToCurrent(); err != nil { + return nil, fmt.Errorf("cannot transform from version %d to %d: %w", version, currentVersion, err) + } + + log.Printf("Loaded cache (version %d), transformed to version %d.", version, currentVersion) + + return cache, nil +} |