/
tracker.go
159 lines (130 loc) · 4.22 KB
/
tracker.go
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
package backup
import (
log "github.com/sirupsen/logrus"
)
type TrackEvents interface {
OnEvent(event ProgressEvent)
}
type TrackScanComplete interface {
OnScanComplete(total MediaCounter)
}
type TrackAnalysed interface {
OnAnalysed(done, total MediaCounter)
}
// TrackUploaded includes both uploaded and skipped
type TrackUploaded interface {
OnUploaded(done, total MediaCounter)
}
// Tracker is consuming progress channel, keep a record of counts, and call listeners
type Tracker struct {
listeners []interface{} // listeners will receive aggregated and typed updates
scanComplete bool
eventCount map[ProgressEventType]MediaCounter
createdAlbums []string
detailedCount map[string]*TypeCounter
Done chan struct{} // Done is closed when all events have been processed.
}
// NewTracker creates the Tracker and start consuming (async)
func NewTracker(progressChannel chan *ProgressEvent, listeners ...interface{}) *Tracker {
tracker := &Tracker{
listeners: listeners,
eventCount: make(map[ProgressEventType]MediaCounter),
detailedCount: make(map[string]*TypeCounter),
Done: make(chan struct{}),
}
go func() {
defer close(tracker.Done)
tracker.consume(progressChannel)
}()
return tracker
}
func (t *Tracker) NewAlbums() []string {
return t.createdAlbums
}
func (t *Tracker) Skipped() MediaCounter {
exists, _ := t.eventCount[ProgressEventAlreadyExists]
duplicates, _ := t.eventCount[ProgressEventDuplicate]
wrongAlbum, _ := t.eventCount[ProgressEventWrongAlbum]
return exists.AddCounter(duplicates).AddCounter(wrongAlbum)
}
func (t *Tracker) CountPerAlbum() map[string]*TypeCounter {
return t.detailedCount
}
func (t *Tracker) WaitToComplete() {
<-t.Done
}
func (t *Tracker) consume(progressChannel chan *ProgressEvent) {
for event := range progressChannel {
t.fireRawEvent(event)
current, _ := t.eventCount[event.Type]
t.eventCount[event.Type] = current.Add(event.Count, event.Size)
switch event.Type {
case ProgressEventScanComplete:
t.scanComplete = true
t.fireScanComplete()
case ProgressEventAnalysed:
case ProgressEventCatalogued:
// nothing
case ProgressEventAlreadyExists,
ProgressEventDuplicate,
ProgressEventWrongAlbum,
ProgressEventReadyForUpload:
t.fireAnalysedEvent()
case ProgressEventUploaded:
typeCount, ok := t.detailedCount[event.Album]
if !ok {
typeCount = &TypeCounter{}
t.detailedCount[event.Album] = typeCount
}
typeCount.IncrementFoundCounter(event.MediaType, event.Count, event.Size)
t.fireUploadedEvent()
case ProgressEventAlbumCreated:
t.createdAlbums = append(t.createdAlbums, event.Album)
default:
log.Warnf("Progress type '%s' is not supported", event.Type)
}
}
}
func (t *Tracker) fireScanComplete() {
for _, listener := range t.listeners {
if dispatch, ok := listener.(TrackScanComplete); ok {
dispatch.OnScanComplete(t.eventCount[ProgressEventScanComplete])
}
}
}
func (t *Tracker) fireAnalysedEvent() {
passed, _ := t.eventCount[ProgressEventReadyForUpload]
exists, _ := t.eventCount[ProgressEventAlreadyExists]
duplicates, _ := t.eventCount[ProgressEventDuplicate]
wrongAlbum, _ := t.eventCount[ProgressEventWrongAlbum]
done := passed.AddCounter(exists).AddCounter(duplicates).AddCounter(wrongAlbum)
for _, listener := range t.listeners {
if dispatch, ok := listener.(TrackAnalysed); ok {
dispatch.OnAnalysed(done, t.eventCount[ProgressEventScanComplete])
}
}
}
func (t *Tracker) fireUploadedEvent() {
scanned, _ := t.eventCount[ProgressEventScanComplete]
exists, _ := t.eventCount[ProgressEventAlreadyExists]
duplicates, _ := t.eventCount[ProgressEventDuplicate]
wrongAlbum, _ := t.eventCount[ProgressEventWrongAlbum]
ready, _ := t.eventCount[ProgressEventReadyForUpload]
uploaded, _ := t.eventCount[ProgressEventUploaded]
total := MediaCounterZero
if ready.AddCounter(duplicates).AddCounter(exists).AddCounter(wrongAlbum).Count == scanned.Count {
total = ready
}
for _, listener := range t.listeners {
if dispatch, ok := listener.(TrackUploaded); ok {
dispatch.OnUploaded(uploaded, total)
}
}
}
func (t *Tracker) fireRawEvent(event *ProgressEvent) {
for _, listener := range t.listeners {
if dispatch, ok := listener.(TrackEvents); ok {
dispatch.OnEvent(*event)
}
}
}