diff options
author | René 'Necoro' Neumann <necoro@necoro.eu> | 2020-08-22 14:26:29 +0200 |
---|---|---|
committer | René 'Necoro' Neumann <necoro@necoro.eu> | 2020-08-22 15:18:33 +0200 |
commit | 8f3a9f1e2f0c9e066d2e3894b9fc2d054d2f148e (patch) | |
tree | 520d24514b66022dbcce3c804adec6d41f038565 /internal/feed | |
parent | eb2b7b872bf70343e6f15c8cbd6ed0fc3e6bfaa7 (diff) | |
download | feed2imap-go-8f3a9f1e2f0c9e066d2e3894b9fc2d054d2f148e.tar.gz feed2imap-go-8f3a9f1e2f0c9e066d2e3894b9fc2d054d2f148e.tar.bz2 feed2imap-go-8f3a9f1e2f0c9e066d2e3894b9fc2d054d2f148e.zip |
Lock cache
Diffstat (limited to '')
-rw-r--r-- | internal/feed/cache.go | 68 | ||||
-rw-r--r-- | internal/feed/cache_v1.go | 2 | ||||
-rw-r--r-- | internal/feed/state.go | 2 |
3 files changed, 59 insertions, 13 deletions
diff --git a/internal/feed/cache.go b/internal/feed/cache.go index 45cefd0..2d8f9aa 100644 --- a/internal/feed/cache.go +++ b/internal/feed/cache.go @@ -8,6 +8,8 @@ import ( "os" "time" + "github.com/nightlyone/lockfile" + "github.com/Necoro/feed2imap-go/pkg/log" ) @@ -17,12 +19,18 @@ const ( currentVersion Version = 1 ) -type Cache interface { +type CacheImpl interface { findItem(*Feed) CachedFeed Version() Version Info() string SpecificInfo(interface{}) string - transformToCurrent() (Cache, error) + transformToCurrent() (CacheImpl, error) +} + +type Cache struct { + CacheImpl + lock lockfile.Lockfile + locked bool } type CachedFeed interface { @@ -34,7 +42,7 @@ type CachedFeed interface { Commit() } -func cacheForVersion(version Version) (Cache, error) { +func cacheForVersion(version Version) (CacheImpl, error) { switch version { case v1Version: return newV1Cache(), nil @@ -43,8 +51,29 @@ func cacheForVersion(version Version) (Cache, error) { } } +func lockName(fileName string) string { + return fileName + ".lck" +} + +func lock(fileName string) (lock lockfile.Lockfile, err error) { + lockFile := lockName(fileName) + log.Debugf("Handling lock file '%s'", lockFile) + + if lock, err = lockfile.New(lockFile); err != nil { + err = fmt.Errorf("Creating lock file: %w", err) + return + } + + if err = lock.TryLock(); err != nil { + err = fmt.Errorf("Locking: %w", err) + return + } + + return +} + func storeCache(cache Cache, fileName string) error { - if cache == nil { + if cache.CacheImpl == nil { return fmt.Errorf("trying to store nil cache") } if cache.Version() != currentVersion { @@ -70,11 +99,23 @@ func storeCache(cache Cache, fileName string) error { writer.Flush() log.Printf("Stored cache to '%s'.", fileName) + if cache.locked { + if err = cache.lock.Unlock(); err != nil { + return fmt.Errorf("Unlocking cache: %w", err) + } + } return nil } func newCache() (Cache, error) { - return cacheForVersion(currentVersion) + cache, err := cacheForVersion(currentVersion) + if err != nil { + return Cache{}, err + } + return Cache{ + CacheImpl: cache, + locked: false, + }, nil } func LoadCache(fileName string) (Cache, error) { @@ -84,33 +125,38 @@ func LoadCache(fileName string) (Cache, error) { // no cache there yet -- make new return newCache() } - return nil, fmt.Errorf("opening cache at '%s': %w", fileName, err) + return Cache{}, fmt.Errorf("opening cache at '%s': %w", fileName, err) } defer f.Close() + lock, err := lock(fileName) + if err != nil { + return Cache{}, err + } + 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) + return Cache{}, fmt.Errorf("reading from '%s': %w", fileName, err) } cache, err := cacheForVersion(Version(version)) if err != nil { - return nil, err + return Cache{}, 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) + return Cache{}, 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) + return Cache{}, 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 + return Cache{cache, lock, true}, nil } diff --git a/internal/feed/cache_v1.go b/internal/feed/cache_v1.go index 656c133..a80e81c 100644 --- a/internal/feed/cache_v1.go +++ b/internal/feed/cache_v1.go @@ -157,7 +157,7 @@ func newV1Cache() *v1Cache { return &cache } -func (cache *v1Cache) transformToCurrent() (Cache, error) { +func (cache *v1Cache) transformToCurrent() (CacheImpl, error) { return cache, nil } diff --git a/internal/feed/state.go b/internal/feed/state.go index dae0917..f2eff72 100644 --- a/internal/feed/state.go +++ b/internal/feed/state.go @@ -154,7 +154,7 @@ func (state *State) Filter() { func NewState(cfg *config.Config) (*State, error) { state := State{ feeds: map[string]*Feed{}, - cache: nil, // loaded later on + cache: Cache{}, // loaded later on cfg: cfg, } |