1- use arc_swap:: ArcSwap ;
1+ use arc_swap:: { ArcSwap , Guard } ;
22use std:: collections:: HashSet ;
33use std:: fs;
44use std:: ops:: RangeInclusive ;
55use std:: path:: Path ;
66use std:: sync:: Arc ;
7+ use std:: time:: Instant ;
78
8- use anyhow:: Context ;
99use chrono:: { Duration , Utc } ;
10+ use log:: error;
1011use serde:: { Deserialize , Serialize } ;
1112
1213use crate :: db;
13- use collector:: Bound ;
14+ use collector:: { Bound , MasterCommit } ;
1415use database:: Date ;
1516
1617use crate :: api:: github;
@@ -100,6 +101,23 @@ pub struct Config {
100101 pub keys : Keys ,
101102}
102103
104+ #[ derive( Debug ) ]
105+ pub struct MasterCommitCache {
106+ pub commits : Vec < MasterCommit > ,
107+ pub updated : Instant ,
108+ }
109+
110+ impl MasterCommitCache {
111+ /// Download the master-branch Rust commit list
112+ pub async fn download ( ) -> anyhow:: Result < Self > {
113+ let commits = collector:: master_commits ( ) . await ?;
114+ Ok ( Self {
115+ commits,
116+ updated : Instant :: now ( ) ,
117+ } )
118+ }
119+ }
120+
103121/// Site context object that contains global data
104122pub struct SiteCtxt {
105123 /// Site configuration
@@ -108,6 +126,8 @@ pub struct SiteCtxt {
108126 pub landing_page : ArcSwap < Option < Arc < crate :: api:: graphs:: Response > > > ,
109127 /// Index of various common queries
110128 pub index : ArcSwap < crate :: db:: Index > ,
129+ /// Cached master-branch Rust commits
130+ pub master_commits : Arc < ArcSwap < MasterCommitCache > > , // outer Arc enables mutation in background task
111131 /// Database connection pool
112132 pub pool : Pool ,
113133}
@@ -160,9 +180,12 @@ impl SiteCtxt {
160180 }
161181 } ;
162182
183+ let master_commits = MasterCommitCache :: download ( ) . await ?;
184+
163185 Ok ( Self {
164186 config,
165187 index : ArcSwap :: new ( Arc :: new ( index) ) ,
188+ master_commits : Arc :: new ( ArcSwap :: new ( Arc :: new ( master_commits) ) ) ,
166189 pool,
167190 landing_page : ArcSwap :: new ( Arc :: new ( None ) ) ,
168191 } )
@@ -175,15 +198,9 @@ impl SiteCtxt {
175198 /// Returns the not yet tested commits
176199 pub async fn missing_commits ( & self ) -> Vec < ( Commit , MissingReason ) > {
177200 let conn = self . conn ( ) . await ;
178- let ( master_commits, queued_pr_commits, in_progress_artifacts) = futures:: join!(
179- collector:: master_commits( ) ,
180- conn. queued_commits( ) ,
181- conn. in_progress_artifacts( )
182- ) ;
183- let master_commits = master_commits
184- . map_err ( |e| anyhow:: anyhow!( "{:?}" , e) )
185- . context ( "getting master commit list" )
186- . unwrap ( ) ;
201+ let ( queued_pr_commits, in_progress_artifacts) =
202+ futures:: join!( conn. queued_commits( ) , conn. in_progress_artifacts( ) ) ;
203+ let master_commits = & self . get_master_commits ( ) . commits ;
187204
188205 let index = self . index . load ( ) ;
189206 let all_commits = index
@@ -193,12 +210,35 @@ impl SiteCtxt {
193210 . collect :: < HashSet < _ > > ( ) ;
194211
195212 calculate_missing (
196- master_commits,
213+ master_commits. clone ( ) ,
197214 queued_pr_commits,
198215 in_progress_artifacts,
199216 all_commits,
200217 )
201218 }
219+
220+ /// Get cached master-branch Rust commits.
221+ /// Returns cached results immediately, but if the cached value is older than one minute,
222+ /// updates in a background task for next time.
223+ pub fn get_master_commits ( & self ) -> Guard < Arc < MasterCommitCache > > {
224+ let commits = self . master_commits . load ( ) ;
225+
226+ if commits. updated . elapsed ( ) > std:: time:: Duration :: from_secs ( 60 ) {
227+ let master_commits = self . master_commits . clone ( ) ;
228+ tokio:: task:: spawn ( async move {
229+ // if another update happens before this one is done, we will download the data twice, but that's it
230+ match MasterCommitCache :: download ( ) . await {
231+ Ok ( commits) => master_commits. store ( Arc :: new ( commits) ) ,
232+ Err ( e) => {
233+ // couldn't get the data, keep serving cached results for now
234+ error ! ( "error retrieving master commit list: {}" , e)
235+ }
236+ }
237+ } ) ;
238+ }
239+
240+ commits
241+ }
202242}
203243
204244/// Calculating the missing commits.
0 commit comments