OLD | NEW |
---|---|
(Empty) | |
1 package db | |
2 | |
3 import ( | |
4 "sync" | |
5 "time" | |
6 ) | |
7 | |
8 type BuildCache struct { | |
9 builds map[string]*Build | |
10 buildsByCommit map[string]map[string]*Build | |
11 db DB | |
12 lastUpdate time.Time | |
13 mtx sync.RWMutex | |
14 queryId string | |
15 } | |
16 | |
17 // GetBuildsForCommits retrieves all builds which first included each of the | |
dogben
2016/08/08 19:22:38
There are a couple things that I don't understand
borenet
2016/08/08 19:51:17
Historically, newer builds "steal" from the blamel
dogben
2016/08/08 20:16:07
Is it worthwhile to mention here that we assume th
borenet
2016/08/09 11:22:55
Wrote some more doc, hopefully it's clearer now.
dogben
2016/08/09 13:56:06
Awesome! Thanks!
| |
18 // given commits. Returns a map whose keys are commit hashes and values are | |
19 // sub-maps whose keys are builder names and values are builds. | |
20 func (c *BuildCache) GetBuildsForCommits(commits []string) (map[string]map[strin g]*Build, error) { | |
21 c.mtx.RLock() | |
22 defer c.mtx.RUnlock() | |
23 | |
24 rv := make(map[string]map[string]*Build, len(commits)) | |
25 for _, commit := range commits { | |
26 if builds, ok := c.buildsByCommit[commit]; ok { | |
27 rv[commit] = make(map[string]*Build, len(builds)) | |
28 for k, v := range builds { | |
29 rv[commit][k] = v.Copy() | |
dogben
2016/08/08 19:22:38
Method doc says the sub-map key is the builder nam
borenet
2016/08/08 19:51:18
Fixed.
| |
30 } | |
31 } else { | |
32 rv[commit] = map[string]*Build{} | |
33 } | |
34 } | |
35 return rv, nil | |
36 } | |
37 | |
38 // update inserts the new/updated builds into the cache. Assumes the caller | |
39 // holds a lock. | |
40 func (c *BuildCache) update(builds []*Build) error { | |
41 for _, b := range builds { | |
42 // If we already know about this build, the blamelist might, | |
43 // have changed, so we need to remove it from buildsByCommit | |
44 // and re-insert where needed. | |
45 if old, ok := c.builds[b.Id]; ok { | |
dogben
2016/08/08 19:22:38
We should think about whether we want to use Build
borenet
2016/08/08 19:51:17
Agreed. I'm just using Buildbucket's IDs for now f
| |
46 for _, commit := range old.Commits { | |
47 delete(c.buildsByCommit[commit], b.Id) | |
48 } | |
49 } | |
50 | |
51 // Insert the new build into the main map. | |
52 c.builds[b.Id] = b.Copy() | |
53 | |
54 // Insert the build into buildsByCommits. | |
55 for _, commit := range b.Commits { | |
56 if _, ok := c.buildsByCommit[commit]; !ok { | |
57 c.buildsByCommit[commit] = map[string]*Build{} | |
58 } | |
59 c.buildsByCommit[commit][b.Id] = b.Copy() | |
dogben
2016/08/08 19:22:38
We should make a single copy and store it in both
borenet
2016/08/08 19:51:18
Done.
| |
60 } | |
61 } | |
62 return nil | |
63 } | |
64 | |
65 // Load new builds from the database. | |
66 func (c *BuildCache) Update() error { | |
67 newBuilds, err := c.db.GetModifiedBuilds(c.queryId) | |
dogben
2016/08/08 19:22:38
nit:
now := time.Now()
newBuilds, err := c.db.Get
borenet
2016/08/08 19:51:18
Good catch, done.
| |
68 c.mtx.Lock() | |
69 defer c.mtx.Unlock() | |
70 if err != nil { | |
71 if err.Error() == ErrUnknownId.Error() { | |
72 // The database may have restarted. Attempt to re-establ ish connection. | |
73 queryId, err := c.db.StartTrackingModifiedBuilds() | |
74 if err != nil { | |
75 return err | |
76 } | |
77 c.queryId = queryId | |
78 // We may have missed something. Query for builds since the last | |
79 // successful query. | |
80 builds, err := c.db.GetBuildsFromDateRange(c.lastUpdate, time.Now()) | |
81 if err != nil { | |
82 return err | |
83 } | |
84 return c.update(builds) | |
85 } else { | |
86 return err | |
87 } | |
88 } | |
89 return c.update(newBuilds) | |
90 } | |
91 | |
92 // NewBuildCache returns a local cache which provides more convenient views of | |
93 // build data than the database can provide. | |
94 func NewBuildCache(db DB, timePeriod time.Duration) (*BuildCache, error) { | |
95 queryId, err := db.StartTrackingModifiedBuilds() | |
96 if err != nil { | |
97 return nil, err | |
98 } | |
99 now := time.Now() | |
100 start := now.Add(-timePeriod) | |
101 builds, err := db.GetBuildsFromDateRange(start, now) | |
102 if err != nil { | |
103 return nil, err | |
104 } | |
105 bc := &BuildCache{ | |
106 builds: map[string]*Build{}, | |
107 buildsByCommit: map[string]map[string]*Build{}, | |
108 db: db, | |
109 lastUpdate: now, | |
110 queryId: queryId, | |
111 } | |
112 bc.update(builds) | |
dogben
2016/08/08 19:22:38
nit: check error (or change update to not return e
borenet
2016/08/08 19:51:17
Done.
| |
113 return bc, nil | |
114 } | |
OLD | NEW |