aboutsummaryrefslogtreecommitdiff
path: root/internal/feed/cache_v1.go
blob: 3d460845d23b790e08ab7d5a4094f5cb9a93b7a1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
package feed

import (
	"crypto/sha256"
	"time"

	"github.com/Necoro/feed2imap-go/pkg/log"
)

const (
	v1Version   Version = 1
	startFeedId uint64  = 1
)

type feedId uint64

type v1Cache struct {
	Ids    map[feedDescriptor]feedId
	NextId uint64
	Feeds  map[feedId]*cachedFeed
}

type cachedFeed struct {
	LastCheck   time.Time
	NumFailures uint // can't be named `Failures` b/c it'll collide with the interface
	Items       []cachedItem
}

type itemHash [sha256.Size]byte

type cachedItem struct {
	Uid     string
	Title   string
	Link    string
	Date    time.Time
	Updated time.Time
	Creator string
	Hash    itemHash
}

func (cf *cachedFeed) Checked(withFailure bool) {
	cf.LastCheck = time.Now()
	if withFailure {
		cf.NumFailures++
	} else {
		cf.NumFailures = 0
	}
}

func (cf *cachedFeed) Failures() uint {
	return cf.NumFailures
}

func (cache *v1Cache) Version() Version {
	return v1Version
}

func newV1Cache() *v1Cache {
	cache := v1Cache{
		Ids:    map[feedDescriptor]feedId{},
		Feeds:  map[feedId]*cachedFeed{},
		NextId: startFeedId,
	}
	return &cache
}

func (cache *v1Cache) transformToCurrent() (Cache, error) {
	return cache, nil
}

func (cache *v1Cache) getItem(id feedId) CachedFeed {
	feed, ok := cache.Feeds[id]
	if !ok {
		feed = &cachedFeed{}
		cache.Feeds[id] = feed
	}
	return feed
}

func (cache *v1Cache) findItem(feed *Feed) CachedFeed {
	if feed.cached != nil {
		return feed.cached.(*cachedFeed)
	}

	fDescr := feed.descriptor()
	id, ok := cache.Ids[fDescr]
	if !ok {
		var otherId feedDescriptor
		changed := false
		for otherId, id = range cache.Ids {
			if otherId.Name == fDescr.Name {
				log.Warnf("Feed %s seems to have changed URLs: newCache '%s', old '%s'. Updating.",
					fDescr.Name, fDescr.Url, otherId.Url)
				changed = true
				break
			} else if otherId.Url == fDescr.Url {
				log.Warnf("Feed with URL '%s' seems to have changed its name: newCache '%s', old '%s'. Updating",
					fDescr.Url, fDescr.Name, otherId.Name)
				changed = true
				break
			}
		}
		if changed {
			delete(cache.Ids, otherId)
		} else {
			id = feedId(cache.NextId)
			cache.NextId++
		}

		cache.Ids[fDescr] = id
	}

	item := cache.getItem(id)
	feed.cached = item
	return item
}