summaryrefslogtreecommitdiff
path: root/system/api/analytics/batch.go
blob: 68ffd65c771171dfe0e374ffba3634a3644b3165 (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
package analytics

import (
	"encoding/json"
	"strconv"
	"time"

	"github.com/boltdb/bolt"
)

// batchInsert is effectively a specialized version of SetContentMulti from the
// db package, iterating over a []apiRequest instead of []url.Values
func batchInsert(requests chan apiRequest) error {
	var reqs []apiRequest
	batchSize := len(requestChan)

	for i := 0; i < batchSize; i++ {
		reqs = append(reqs, <-requestChan)
	}

	err := store.Update(func(tx *bolt.Tx) error {
		b, err := tx.CreateBucketIfNotExists([]byte("__requests"))
		if err != nil {
			return err
		}

		for _, apiReq := range reqs {
			// get the next available ID and convert to string
			// also set effectedID to int of ID
			id, err := b.NextSequence()
			if err != nil {
				return err
			}
			cid := strconv.FormatUint(id, 10)

			j, err := json.Marshal(apiReq)
			if err != nil {
				return err
			}

			err = b.Put([]byte(cid), j)
			if err != nil {
				return err
			}
		}

		return nil

	})
	if err != nil {
		return err
	}

	return nil
}

// batchPrune takes a duration to evaluate apiRequest dates against. If any of
// the apiRequest timestamps are before the threshold, they are removed.
// TODO: add feature to alternatively backup old analytics to cloud
func batchPrune(threshold time.Duration) error {
	now := time.Now()
	today := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.UTC)
	max := today.Add(threshold)

	// iterate through all request data
	err := store.Update(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte("__requests"))

		err := b.ForEach(func(k, v []byte) error {
			var r apiRequest
			err := json.Unmarshal(v, &r)
			if err != nil {
				return err
			}

			// delete if timestamp is below or equal to max
			ts := time.Unix(r.Timestamp/1000, 0)
			if ts.Equal(max) || ts.Before(max) {
				err := b.Delete(k)
				if err != nil {
					return err
				}
			}

			return nil
		})
		if err != nil {
			return err
		}

		return nil
	})
	if err != nil {
		return err
	}

	return nil
}