Chromium Code Reviews| 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 |