@@ -10,22 +10,23 @@ use std::sync::{mpsc, Arc, Mutex};
10
10
use std:: thread;
11
11
use std:: time:: Duration ;
12
12
use utils;
13
+ use report:: { Comparison , TestResults } ;
13
14
14
15
// Automatically wake up the reports generator thread every 10 minutes to check for new jobs
15
16
const AUTOMATIC_THREAD_WAKEUP : u64 = 600 ;
16
17
17
- fn generate_report ( data : & Data , ex : & Experiment , results : & DatabaseDB ) -> Fallible < ( ) > {
18
+ fn generate_report ( data : & Data , ex : & Experiment , results : & DatabaseDB ) -> Fallible < ( TestResults ) > {
18
19
let client = S3Client :: new_with (
19
20
HttpClient :: new ( ) ?,
20
21
data. tokens . reports_bucket . to_aws_credentials ( ) ,
21
22
data. tokens . reports_bucket . region . to_region ( ) ?,
22
- ) ;
23
+ ) ;
23
24
let dest = format ! ( "s3://{}/{}" , data. tokens. reports_bucket. bucket, & ex. name) ;
24
25
let writer = report:: S3Writer :: create ( Box :: new ( client) , dest. parse ( ) ?) ?;
25
26
26
- report:: gen ( results, & ex, & writer, & data. config ) ?;
27
+ let res = report:: gen ( results, & ex, & writer, & data. config ) ?;
27
28
28
- Ok ( ( ) )
29
+ Ok ( res )
29
30
}
30
31
31
32
fn reports_thread ( data : & Data , wakes : & mpsc:: Receiver < ( ) > ) -> Fallible < ( ) > {
@@ -36,111 +37,130 @@ fn reports_thread(data: &Data, wakes: &mpsc::Receiver<()>) -> Fallible<()> {
36
37
let mut ex = match Experiment :: first_by_status ( & data. db , Status :: NeedsReport ) ? {
37
38
Some ( ex) => ex,
38
39
None => {
39
- // This will sleep AUTOMATIC_THREAD_WAKEUP seconds *or* until a wake is received
40
- if let Err ( mpsc:: RecvTimeoutError :: Disconnected ) = wakes. recv_timeout ( timeout) {
41
- thread:: sleep ( timeout) ;
42
- }
43
-
44
- continue ;
40
+ // This will sleep AUTOMATIC_THREAD_WAKEUP seconds *or* until a wake is received
41
+ if let Err ( mpsc:: RecvTimeoutError :: Disconnected ) = wakes. recv_timeout ( timeout) {
42
+ thread:: sleep ( timeout) ;
45
43
}
46
- } ;
47
- let name = ex. name . clone ( ) ;
48
44
49
- info ! ( "generating report for experiment {}..." , name) ;
50
- ex. set_status ( & data. db , Status :: GeneratingReport ) ?;
45
+ continue ;
46
+ }
47
+ } ;
48
+ let name = ex. name . clone ( ) ;
49
+
50
+ info ! ( "generating report for experiment {}..." , name) ;
51
+ ex. set_status ( & data. db , Status :: GeneratingReport ) ?;
51
52
52
- if let Err ( err) = generate_report ( data, & ex, & results) {
53
+ match generate_report ( data, & ex, & results) {
54
+ Err ( err) => {
53
55
ex. set_status ( & data. db , Status :: ReportFailed ) ?;
54
56
error ! ( "failed to generate the report of {}" , name) ;
55
57
utils:: report_failure ( & err) ;
56
58
57
59
if let Some ( ref github_issue) = ex. github_issue {
58
60
Message :: new ( )
59
- . line (
60
- "rotating_light" ,
61
- format ! ( "Report generation of **`{}`** failed: {}" , name, err) ,
61
+ . line (
62
+ "rotating_light" ,
63
+ format ! ( "Report generation of **`{}`** failed: {}" , name, err) ,
62
64
) . line (
63
- "hammer_and_wrench" ,
64
- "If the error is fixed use the `retry-report` command." ,
65
+ "hammer_and_wrench" ,
66
+ "If the error is fixed use the `retry-report` command." ,
65
67
) . note (
66
- "sos" ,
67
- "Can someone from the infra team check in on this? @rust-lang/infra" ,
68
+ "sos" ,
69
+ "Can someone from the infra team check in on this? @rust-lang/infra" ,
68
70
) . send ( & github_issue. api_url , data) ?;
69
- }
71
+ }
70
72
71
- continue ;
73
+ continue ;
74
+ } ,
75
+ Ok ( res) => {
76
+
77
+ let base_url = data
78
+ . tokens
79
+ . reports_bucket
80
+ . public_url
81
+ . replace ( "{bucket}" , & data. tokens . reports_bucket . bucket ) ;
82
+ let report_url = format ! ( "{}/{}/index.html" , base_url, name) ;
83
+
84
+ ex. set_status ( & data. db , Status :: Completed ) ?;
85
+ ex. set_report_url ( & data. db , & report_url) ?;
86
+ info ! ( "report for the experiment {} generated successfully!" , name) ;
87
+
88
+ let ( mut regressed, mut fixed, mut skipped, mut error) = ( 0 , 0 , 0 , 0 ) ;
89
+ res. crates . iter ( ) . for_each ( |krate|
90
+ match krate. res {
91
+ Comparison :: Regressed => regressed = regressed + 1 ,
92
+ Comparison :: Fixed => fixed = fixed + 1 ,
93
+ Comparison :: Skipped => skipped = skipped + 1 ,
94
+ Comparison :: Error => error = error +1 ,
95
+ _ => ( ) ,
96
+ }
97
+ ) ;
98
+
99
+
100
+ if let Some ( ref github_issue) = ex. github_issue {
101
+ Message :: new ( )
102
+ . line ( "tada" , format ! ( "Experiment **`{}`** is completed!" , name) )
103
+ . line (
104
+ "newspaper" ,
105
+ format ! ( "[Open the full report]({})." , report_url) ,
106
+ ) . line (
107
+ "hash" ,
108
+ format ! ( " {} | :arrow_left: {} | :white_check_mark: {} | :fast_forward: {} | :x: {}" , res. crates. len( ) , regressed, fixed, skipped, error) ,
109
+ ) . note (
110
+ "warning" ,
111
+ format ! (
112
+ "If you notice any spurious failure [please add them to the \
113
+ blacklist]({}/blob/master/config.toml)!",
114
+ :: CRATER_REPO_URL ,
115
+ ) ,
116
+ ) . set_label ( Label :: ExperimentCompleted )
117
+ . send ( & github_issue. api_url , data) ?;
118
+ }
119
+ }
120
+ }
72
121
}
122
+ }
73
123
74
- let base_url = data
75
- . tokens
76
- . reports_bucket
77
- . public_url
78
- . replace ( "{bucket}" , & data. tokens . reports_bucket . bucket ) ;
79
- let report_url = format ! ( "{}/{}/index.html" , base_url, name) ;
80
-
81
- ex. set_status ( & data. db , Status :: Completed ) ?;
82
- ex. set_report_url ( & data. db , & report_url) ?;
83
- info ! ( "report for the experiment {} generated successfully!" , name) ;
124
+ #[ derive( Clone , Default ) ]
125
+ pub struct ReportsWorker ( Arc < Mutex < Option < mpsc:: Sender < ( ) > > > > ) ;
84
126
85
- if let Some ( ref github_issue) = ex. github_issue {
86
- Message :: new ( )
87
- . line ( "tada" , format ! ( "Experiment **`{}`** is completed!" , name) )
88
- . line (
89
- "newspaper" ,
90
- format ! ( "[Open the full report]({})." , report_url) ,
91
- ) . note (
92
- "warning" ,
93
- format ! (
94
- "If you notice any spurious failure [please add them to the \
95
- blacklist]({}/blob/master/config.toml)!",
96
- :: CRATER_REPO_URL ,
97
- ) ,
98
- ) . set_label ( Label :: ExperimentCompleted )
99
- . send ( & github_issue. api_url , data) ?;
127
+ impl ReportsWorker {
128
+ pub fn new ( ) -> Self {
129
+ ReportsWorker ( Arc :: new ( Mutex :: new ( None ) ) )
100
130
}
101
- }
102
- }
103
131
104
- #[ derive( Clone , Default ) ]
105
- pub struct ReportsWorker ( Arc < Mutex < Option < mpsc:: Sender < ( ) > > > > ) ;
106
-
107
- impl ReportsWorker {
108
- pub fn new ( ) -> Self {
109
- ReportsWorker ( Arc :: new ( Mutex :: new ( None ) ) )
110
- }
132
+ pub fn spawn ( & self , data : Data ) {
133
+ let waker = self . 0 . clone ( ) ;
134
+ thread:: spawn ( move || {
135
+ // Set up a new waker channel
136
+ let ( wake_send, wake_recv) = mpsc:: channel ( ) ;
137
+ {
138
+ let mut waker = waker. lock ( ) . unwrap ( ) ;
139
+ * waker = Some ( wake_send) ;
140
+ }
111
141
112
- pub fn spawn ( & self , data : Data ) {
113
- let waker = self . 0 . clone ( ) ;
114
- thread:: spawn ( move || {
115
- // Set up a new waker channel
116
- let ( wake_send, wake_recv) = mpsc:: channel ( ) ;
117
- {
118
- let mut waker = waker. lock ( ) . unwrap ( ) ;
119
- * waker = Some ( wake_send) ;
142
+ loop {
143
+ let result = reports_thread ( & data. clone ( ) , & wake_recv)
144
+ . with_context ( |_| "the reports generator thread crashed" ) ;
145
+ if let Err ( e) = result {
146
+ utils:: report_failure ( & e) ;
120
147
}
121
148
122
- loop {
123
- let result = reports_thread ( & data. clone ( ) , & wake_recv)
124
- . with_context ( |_| "the reports generator thread crashed" ) ;
125
- if let Err ( e) = result {
126
- utils:: report_failure ( & e) ;
127
- }
128
-
129
- warn ! ( "the reports generator thread will be respawned in one minute" ) ;
130
- thread:: sleep ( Duration :: from_secs ( 60 ) ) ;
131
- }
132
- } ) ;
133
- }
149
+ warn ! ( "the reports generator thread will be respawned in one minute" ) ;
150
+ thread:: sleep ( Duration :: from_secs ( 60 ) ) ;
151
+ }
152
+ } ) ;
153
+ }
134
154
135
- pub fn wake ( & self ) {
136
- // We don't really care if the wake fails: the reports generator thread wakes up on its own
137
- // every few minutes, so this just speeds up the process
138
- if let Some ( waker) = self . 0 . lock ( ) . ok ( ) . as_ref ( ) . and_then ( |opt| opt. as_ref ( ) ) {
139
- if waker. send ( ( ) ) . is_err ( ) {
140
- warn ! ( "can't wake the reports generator, will have to wait" ) ;
141
- }
142
- } else {
143
- warn ! ( "no report generator to wake up!" ) ;
155
+ pub fn wake ( & self ) {
156
+ // We don't really care if the wake fails: the reports generator thread wakes up on its own
157
+ // every few minutes, so this just speeds up the process
158
+ if let Some ( waker) = self . 0 . lock ( ) . ok ( ) . as_ref ( ) . and_then ( |opt| opt. as_ref ( ) ) {
159
+ if waker. send ( ( ) ) . is_err ( ) {
160
+ warn ! ( "can't wake the reports generator, will have to wait" ) ;
144
161
}
162
+ } else {
163
+ warn ! ( "no report generator to wake up!" ) ;
145
164
}
146
165
}
166
+ }
0 commit comments