55//! cargo run --bin monitor
66
77use anyhow:: Result ;
8+ use crates_io:: tasks:: spawn_blocking;
89use crates_io:: worker:: jobs;
910use crates_io:: { admin:: on_call, db, schema:: * } ;
1011use crates_io_env_vars:: { var, var_parsed} ;
1112use crates_io_worker:: BackgroundJob ;
1213use diesel:: prelude:: * ;
14+ use diesel_async:: { AsyncPgConnection , RunQueryDsl } ;
1315
14- fn main ( ) -> Result < ( ) > {
15- let conn = & mut db:: oneoff_connection ( ) ?;
16+ #[ tokio:: main]
17+ async fn main ( ) -> Result < ( ) > {
18+ let conn = & mut db:: oneoff_async_connection ( ) . await ?;
1619
17- check_failing_background_jobs ( conn) ?;
18- check_stalled_update_downloads ( conn) ?;
19- check_spam_attack ( conn) ?;
20+ check_failing_background_jobs ( conn) . await ?;
21+ check_stalled_update_downloads ( conn) . await ?;
22+ check_spam_attack ( conn) . await ?;
2023 Ok ( ( ) )
2124}
2225
@@ -28,7 +31,7 @@ fn main() -> Result<()> {
2831///
2932/// Within the default 15 minute time, a job should have already had several
3033/// failed retry attempts.
31- fn check_failing_background_jobs ( conn : & mut PgConnection ) -> Result < ( ) > {
34+ async fn check_failing_background_jobs ( conn : & mut AsyncPgConnection ) -> Result < ( ) > {
3235 use diesel:: dsl:: * ;
3336 use diesel:: sql_types:: Integer ;
3437
@@ -45,7 +48,8 @@ fn check_failing_background_jobs(conn: &mut PgConnection) -> Result<()> {
4548 . filter ( background_jobs:: priority. ge ( 0 ) )
4649 . for_update ( )
4750 . skip_locked ( )
48- . load ( conn) ?;
51+ . load ( conn)
52+ . await ?;
4953
5054 let stalled_job_count = stalled_jobs. len ( ) ;
5155
@@ -63,12 +67,13 @@ fn check_failing_background_jobs(conn: &mut PgConnection) -> Result<()> {
6367 }
6468 } ;
6569
66- log_and_trigger_event ( event) ?;
70+ spawn_blocking ( move || log_and_trigger_event ( event) ) . await ?;
71+
6772 Ok ( ( ) )
6873}
6974
7075/// Check for an `update_downloads` job that has run longer than expected
71- fn check_stalled_update_downloads ( conn : & mut PgConnection ) -> Result < ( ) > {
76+ async fn check_stalled_update_downloads ( conn : & mut AsyncPgConnection ) -> Result < ( ) > {
7277 use chrono:: { DateTime , NaiveDateTime , Utc } ;
7378
7479 const EVENT_KEY : & str = "update_downloads_stalled" ;
@@ -81,28 +86,35 @@ fn check_stalled_update_downloads(conn: &mut PgConnection) -> Result<()> {
8186 let start_time: Result < NaiveDateTime , _ > = background_jobs:: table
8287 . filter ( background_jobs:: job_type. eq ( jobs:: UpdateDownloads :: JOB_NAME ) )
8388 . select ( background_jobs:: created_at)
84- . first ( conn) ;
89+ . first ( conn)
90+ . await ;
8591
8692 if let Ok ( start_time) = start_time {
8793 let start_time = DateTime :: < Utc > :: from_naive_utc_and_offset ( start_time, Utc ) ;
8894 let minutes = Utc :: now ( ) . signed_duration_since ( start_time) . num_minutes ( ) ;
8995
9096 if minutes > max_job_time {
91- return log_and_trigger_event ( on_call:: Event :: Trigger {
92- incident_key : Some ( EVENT_KEY . into ( ) ) ,
93- description : format ! ( "update_downloads job running for {minutes} minutes" ) ,
94- } ) ;
97+ return spawn_blocking ( move || {
98+ log_and_trigger_event ( on_call:: Event :: Trigger {
99+ incident_key : Some ( EVENT_KEY . into ( ) ) ,
100+ description : format ! ( "update_downloads job running for {minutes} minutes" ) ,
101+ } )
102+ } )
103+ . await ;
95104 }
96105 } ;
97106
98- log_and_trigger_event ( on_call:: Event :: Resolve {
99- incident_key : EVENT_KEY . into ( ) ,
100- description : Some ( "No stalled update_downloads job" . into ( ) ) ,
107+ spawn_blocking ( move || {
108+ log_and_trigger_event ( on_call:: Event :: Resolve {
109+ incident_key : EVENT_KEY . into ( ) ,
110+ description : Some ( "No stalled update_downloads job" . into ( ) ) ,
111+ } )
101112 } )
113+ . await
102114}
103115
104116/// Check for known spam patterns
105- fn check_spam_attack ( conn : & mut PgConnection ) -> Result < ( ) > {
117+ async fn check_spam_attack ( conn : & mut AsyncPgConnection ) -> Result < ( ) > {
106118 use crates_io:: sql:: canon_crate_name;
107119
108120 const EVENT_KEY : & str = "spam_attack" ;
@@ -121,6 +133,7 @@ fn check_spam_attack(conn: &mut PgConnection) -> Result<()> {
121133 . filter ( canon_crate_name ( crates:: name) . eq_any ( bad_crate_names) )
122134 . select ( crates:: name)
123135 . first ( conn)
136+ . await
124137 . optional ( ) ?;
125138
126139 if let Some ( bad_crate) = bad_crate {
@@ -139,7 +152,7 @@ fn check_spam_attack(conn: &mut PgConnection) -> Result<()> {
139152 }
140153 } ;
141154
142- log_and_trigger_event ( event) ?;
155+ spawn_blocking ( move || log_and_trigger_event ( event) ) . await ?;
143156 Ok ( ( ) )
144157}
145158
0 commit comments