@@ -160,103 +160,211 @@ impl SiteCtxt {
160160 . unwrap ( ) ;
161161
162162 let index = self . index . load ( ) ;
163- let mut all_commits = index
163+ let all_commits = index
164164 . commits ( )
165165 . iter ( )
166166 . map ( |commit| commit. sha . clone ( ) )
167167 . collect :: < HashSet < _ > > ( ) ;
168168
169- let now = Utc :: now ( ) ;
170- let mut master_commits = master_commits
171- . into_iter ( )
172- . filter ( |c| now. signed_duration_since ( c. time ) < Duration :: days ( 29 ) )
173- . map ( |c| {
174- (
175- Commit {
176- sha : c. sha ,
177- date : Date ( c. time ) ,
178- } ,
179- // All recent master commits should have an associated PR
180- MissingReason :: Master {
181- pr : c. pr . unwrap_or ( 0 ) ,
182- parent_sha : c. parent_sha ,
183- } ,
184- )
185- } )
186- . collect :: < Vec < _ > > ( ) ;
187- master_commits. reverse ( ) ;
169+ calculate_missing (
170+ master_commits,
171+ queued_pr_commits,
172+ in_progress_artifacts,
173+ all_commits,
174+ )
175+ }
176+ }
188177
189- let mut missing = Vec :: with_capacity ( queued_pr_commits. len ( ) * 2 + master_commits. len ( ) ) ; // Two commits per every try commit and all master commits
190- for database:: QueuedCommit {
191- sha,
192- parent_sha,
193- pr,
194- include,
195- exclude,
196- runs,
197- } in queued_pr_commits
198- . into_iter ( )
199- // filter out any queued PR master commits (leaving only try commits)
200- . filter ( |c| !master_commits. iter ( ) . any ( |( mc, _) | mc. sha == c. sha ) )
201- {
202- // Enqueue the `TryParent` commit before the `TryCommit` itself, so that
203- // all of the `try` run's data is complete when the benchmark results
204- // of that commit are available.
205- if let Some ( ( try_parent, _) ) = master_commits
206- . iter ( )
207- . find ( |( m, _) | m. sha == parent_sha. as_str ( ) )
208- {
209- missing. push ( ( try_parent. clone ( ) , MissingReason :: TryParent ) ) ;
210- }
211- missing. push ( (
178+ fn calculate_missing (
179+ master_commits : Vec < collector:: MasterCommit > ,
180+ queued_pr_commits : Vec < database:: QueuedCommit > ,
181+ in_progress_artifacts : Vec < ArtifactId > ,
182+ mut all_commits : HashSet < String > ,
183+ ) -> Vec < ( Commit , MissingReason ) > {
184+ let now = Utc :: now ( ) ;
185+ let mut master_commits = master_commits
186+ . into_iter ( )
187+ . filter ( |c| now. signed_duration_since ( c. time ) < Duration :: days ( 29 ) )
188+ . map ( |c| {
189+ (
212190 Commit {
213- sha : sha . to_string ( ) ,
214- date : Date :: ymd_hms ( 2001 , 01 , 01 , 0 , 0 , 0 ) ,
191+ sha : c . sha ,
192+ date : Date ( c . time ) ,
215193 } ,
216- MissingReason :: Try {
217- pr,
218- include,
219- exclude,
220- runs,
194+ // All recent master commits should have an associated PR
195+ MissingReason :: Master {
196+ pr : c. pr . unwrap_or ( 0 ) ,
197+ parent_sha : c. parent_sha ,
221198 } ,
222- ) ) ;
199+ )
200+ } )
201+ . collect :: < Vec < _ > > ( ) ;
202+ master_commits. reverse ( ) ;
203+ let mut missing = Vec :: with_capacity ( queued_pr_commits. len ( ) * 2 + master_commits. len ( ) ) ;
204+ for database:: QueuedCommit {
205+ sha,
206+ parent_sha,
207+ pr,
208+ include,
209+ exclude,
210+ runs,
211+ } in queued_pr_commits
212+ . into_iter ( )
213+ // filter out any queued PR master commits (leaving only try commits)
214+ . filter ( |c| !master_commits. iter ( ) . any ( |( mc, _) | mc. sha == c. sha ) )
215+ {
216+ // Enqueue the `TryParent` commit before the `TryCommit` itself, so that
217+ // all of the `try` run's data is complete when the benchmark results
218+ // of that commit are available.
219+ if let Some ( ( try_parent, _) ) = master_commits
220+ . iter ( )
221+ . find ( |( m, _) | m. sha == parent_sha. as_str ( ) )
222+ {
223+ missing. push ( ( try_parent. clone ( ) , MissingReason :: TryParent ) ) ;
223224 }
224- missing. extend ( master_commits) ;
225-
226- for aid in in_progress_artifacts {
227- match aid {
228- ArtifactId :: Commit ( c) => {
229- let previous = missing
230- . iter ( )
231- . find ( |( i, _) | i. sha == c. sha )
232- . map ( |v| Box :: new ( v. 1 . clone ( ) ) ) ;
233- all_commits. remove ( & c. sha ) ;
234- missing. insert ( 0 , ( c, MissingReason :: InProgress ( previous) ) ) ;
235- }
236- ArtifactId :: Tag ( _) => {
237- // do nothing, for now, though eventually we'll want an artifact queue
238- }
225+ missing. push ( (
226+ Commit {
227+ sha : sha. to_string ( ) ,
228+ date : Date :: ymd_hms ( 2001 , 01 , 01 , 0 , 0 , 0 ) ,
229+ } ,
230+ MissingReason :: Try {
231+ pr,
232+ include,
233+ exclude,
234+ runs,
235+ } ,
236+ ) ) ;
237+ }
238+ missing. extend ( master_commits) ;
239+ for aid in in_progress_artifacts {
240+ match aid {
241+ ArtifactId :: Commit ( c) => {
242+ let previous = missing
243+ . iter ( )
244+ . find ( |( i, _) | i. sha == c. sha )
245+ . map ( |v| Box :: new ( v. 1 . clone ( ) ) ) ;
246+ all_commits. remove ( & c. sha ) ;
247+ missing. insert ( 0 , ( c, MissingReason :: InProgress ( previous) ) ) ;
239248 }
240- }
241-
242- let mut already_tested = HashSet :: with_capacity ( all_commits. len ( ) ) ;
243- already_tested. extend ( all_commits) ;
244-
245- // Remove commits from missing that have already been tested
246- // FIXME: replace with Vec::drain_filter when it stabilizes
247- let mut i = 0 ;
248- while i != missing. len ( ) {
249- if !already_tested. insert ( missing[ i] . 0 . sha . clone ( ) ) {
250- missing. remove ( i) ;
251- } else {
252- i += 1 ;
249+ ArtifactId :: Tag ( _) => {
250+ // do nothing, for now, though eventually we'll want an artifact queue
253251 }
254252 }
255-
256- missing
257253 }
254+ let mut already_tested = HashSet :: with_capacity ( all_commits. len ( ) ) ;
255+ already_tested. extend ( all_commits) ;
256+ let mut i = 0 ;
257+ while i != missing. len ( ) {
258+ if !already_tested. insert ( missing[ i] . 0 . sha . clone ( ) ) {
259+ missing. remove ( i) ;
260+ } else {
261+ i += 1 ;
262+ }
263+ }
264+ missing
258265}
259266
260267/// One decimal place rounded percent
261268#[ derive( Debug , Copy , Clone , PartialEq , Serialize , Deserialize ) ]
262269pub struct Percent ( #[ serde( with = "collector::round_float" ) ] pub f64 ) ;
270+
271+ #[ cfg( test) ]
272+ mod tests {
273+ use std:: str:: FromStr ;
274+
275+ use collector:: MasterCommit ;
276+ use database:: QueuedCommit ;
277+
278+ use super :: * ;
279+ #[ test]
280+ fn calculates_missing_correct ( ) {
281+ let time = chrono:: DateTime :: from_str ( "2021-09-01T00:00:00.000Z" ) . unwrap ( ) ;
282+ let master_commits = vec ! [
283+ // A not yet tested commit
284+ MasterCommit {
285+ sha: "123" . into( ) ,
286+ parent_sha: "345" . into( ) ,
287+ pr: Some ( 11 ) ,
288+ time,
289+ } ,
290+ // An already tested commit
291+ MasterCommit {
292+ sha: "abc" . into( ) ,
293+ parent_sha: "def" . into( ) ,
294+ pr: Some ( 90 ) ,
295+ time,
296+ } ,
297+ // A queued PR commit
298+ MasterCommit {
299+ sha: "foo" . into( ) ,
300+ parent_sha: "bar" . into( ) ,
301+ pr: Some ( 77 ) ,
302+ time,
303+ } ,
304+ ] ;
305+ let queued_pr_commits = vec ! [
306+ // A master commit
307+ QueuedCommit {
308+ sha: "foo" . into( ) ,
309+ parent_sha: "bar" . into( ) ,
310+ pr: 77 ,
311+ include: None ,
312+ exclude: None ,
313+ runs: None ,
314+ } ,
315+ // A try run
316+ QueuedCommit {
317+ sha: "baz" . into( ) ,
318+ parent_sha: "foo" . into( ) ,
319+ pr: 101 ,
320+ include: None ,
321+ exclude: None ,
322+ runs: None ,
323+ } ,
324+ ] ;
325+ let in_progress_artifacts = vec ! [ ] ;
326+ let mut all_commits = HashSet :: new ( ) ;
327+ all_commits. insert ( master_commits[ 1 ] . sha . clone ( ) ) ;
328+
329+ let expected = vec ! [
330+ (
331+ Commit {
332+ sha: "foo" . into( ) ,
333+ date: database:: Date ( time) ,
334+ } ,
335+ MissingReason :: TryParent ,
336+ ) ,
337+ (
338+ Commit {
339+ sha: "baz" . into( ) ,
340+ date: database:: Date ( time) ,
341+ } ,
342+ MissingReason :: Try {
343+ pr: 101 ,
344+ include: None ,
345+ exclude: None ,
346+ runs: None ,
347+ } ,
348+ ) ,
349+ (
350+ Commit {
351+ sha: "123" . into( ) ,
352+ date: database:: Date ( time) ,
353+ } ,
354+ MissingReason :: Master {
355+ pr: 11 ,
356+ parent_sha: "345" . into( ) ,
357+ } ,
358+ ) ,
359+ ] ;
360+ assert_eq ! (
361+ expected,
362+ calculate_missing(
363+ master_commits,
364+ queued_pr_commits,
365+ in_progress_artifacts,
366+ all_commits
367+ )
368+ ) ;
369+ }
370+ }
0 commit comments