@@ -17,6 +17,7 @@ limitations under the License.
1717package flakesync
1818
1919import (
20+ "container/list"
2021 "sort"
2122 "sync"
2223 "time"
@@ -48,6 +49,9 @@ const (
4849 // RunBrokenTestName names a "flake" which really represents the fact
4950 // that the entire run was broken.
5051 RunBrokenTestName Test = "Suite so broken it failed to produce JUnit output"
52+
53+ // Maximum number of flakes to keep in memory.
54+ maxFlakes = 20000
5155)
5256
5357// Result records a test job completion.
@@ -98,6 +102,8 @@ type Cache struct {
98102 lock sync.Mutex
99103 byJob jobMap
100104 flakeQueue flakeMap
105+ expireList * list.List
106+ maxFlakes int // tests can modify this
101107
102108 // only one expensive lookup at a time. Also, don't lock the cache
103109 // while we're doing an expensive update. If you lock both locks, you
@@ -115,7 +121,9 @@ func NewCache(getFunc ResultFunc) *Cache {
115121 c := & Cache {
116122 byJob : jobMap {},
117123 flakeQueue : flakeMap {},
124+ expireList : list .New (),
118125 doExpensiveLookup : getFunc ,
126+ maxFlakes : maxFlakes ,
119127 }
120128 return c
121129}
@@ -157,13 +165,21 @@ func (c *Cache) populate(j Job, n Number) (*Result, error) {
157165
158166 // Add any flakes to the queue.
159167 for f , reason := range r .Flakes {
160- c .flakeQueue [flakeKey {j , n , f }] = & Flake {
168+ k := flakeKey {j , n , f }
169+ c .flakeQueue [k ] = & Flake {
161170 Job : j ,
162171 Number : n ,
163172 Test : f ,
164173 Reason : reason ,
165174 Result : r ,
166175 }
176+ c .expireList .PushFront (k )
177+ // kick out old flakes if we have too many.
178+ for len (c .flakeQueue ) > c .maxFlakes {
179+ e := c .expireList .Back ()
180+ delete (c .flakeQueue , e .Value .(flakeKey ))
181+ c .expireList .Remove (e )
182+ }
167183 }
168184 return r , nil
169185}
0 commit comments