1
- use arc_swap:: ArcSwap ;
1
+ use arc_swap:: { ArcSwap , Guard } ;
2
2
use std:: collections:: HashSet ;
3
3
use std:: fs;
4
4
use std:: ops:: RangeInclusive ;
5
5
use std:: path:: Path ;
6
6
use std:: sync:: Arc ;
7
+ use std:: time:: Instant ;
7
8
8
- use anyhow:: Context ;
9
9
use chrono:: { Duration , Utc } ;
10
+ use log:: error;
10
11
use serde:: { Deserialize , Serialize } ;
11
12
12
13
use crate :: db;
13
- use collector:: Bound ;
14
+ use collector:: { Bound , MasterCommit } ;
14
15
use database:: Date ;
15
16
16
17
use crate :: api:: github;
@@ -100,6 +101,23 @@ pub struct Config {
100
101
pub keys : Keys ,
101
102
}
102
103
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
+
103
121
/// Site context object that contains global data
104
122
pub struct SiteCtxt {
105
123
/// Site configuration
@@ -108,6 +126,8 @@ pub struct SiteCtxt {
108
126
pub landing_page : ArcSwap < Option < Arc < crate :: api:: graphs:: Response > > > ,
109
127
/// Index of various common queries
110
128
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
111
131
/// Database connection pool
112
132
pub pool : Pool ,
113
133
}
@@ -160,9 +180,12 @@ impl SiteCtxt {
160
180
}
161
181
} ;
162
182
183
+ let master_commits = MasterCommitCache :: download ( ) . await ?;
184
+
163
185
Ok ( Self {
164
186
config,
165
187
index : ArcSwap :: new ( Arc :: new ( index) ) ,
188
+ master_commits : Arc :: new ( ArcSwap :: new ( Arc :: new ( master_commits) ) ) ,
166
189
pool,
167
190
landing_page : ArcSwap :: new ( Arc :: new ( None ) ) ,
168
191
} )
@@ -175,15 +198,9 @@ impl SiteCtxt {
175
198
/// Returns the not yet tested commits
176
199
pub async fn missing_commits ( & self ) -> Vec < ( Commit , MissingReason ) > {
177
200
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 ;
187
204
188
205
let index = self . index . load ( ) ;
189
206
let all_commits = index
@@ -193,12 +210,35 @@ impl SiteCtxt {
193
210
. collect :: < HashSet < _ > > ( ) ;
194
211
195
212
calculate_missing (
196
- master_commits,
213
+ master_commits. clone ( ) ,
197
214
queued_pr_commits,
198
215
in_progress_artifacts,
199
216
all_commits,
200
217
)
201
218
}
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
+ }
202
242
}
203
243
204
244
/// Calculating the missing commits.
0 commit comments