Skip to content

Commit 5faabd6

Browse files
authored
Merge pull request #9578 from Turbo87/async-monitor
bin/monitor: Convert to async
2 parents b692905 + 9888fd1 commit 5faabd6

File tree

2 files changed

+45
-20
lines changed

2 files changed

+45
-20
lines changed

src/bin/monitor.rs

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,21 @@
55
//! cargo run --bin monitor
66
77
use anyhow::Result;
8+
use crates_io::tasks::spawn_blocking;
89
use crates_io::worker::jobs;
910
use crates_io::{admin::on_call, db, schema::*};
1011
use crates_io_env_vars::{var, var_parsed};
1112
use crates_io_worker::BackgroundJob;
1213
use 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

src/db.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::certs::CRUNCHY;
22
use diesel::{Connection, ConnectionResult, PgConnection, QueryResult};
33
use diesel_async::pooled_connection::deadpool::{Hook, HookError};
44
use diesel_async::pooled_connection::ManagerConfig;
5-
use diesel_async::{AsyncPgConnection, RunQueryDsl};
5+
use diesel_async::{AsyncConnection, AsyncPgConnection, RunQueryDsl};
66
use native_tls::{Certificate, TlsConnector};
77
use postgres_native_tls::MakeTlsConnector;
88
use secrecy::ExposeSecret;
@@ -23,6 +23,18 @@ pub fn oneoff_connection() -> anyhow::Result<PgConnection> {
2323
oneoff_connection_with_config(&config).map_err(Into::into)
2424
}
2525

26+
pub async fn oneoff_async_connection_with_config(
27+
config: &config::DatabasePools,
28+
) -> ConnectionResult<AsyncPgConnection> {
29+
let url = connection_url(config, config.primary.url.expose_secret());
30+
AsyncPgConnection::establish(&url).await
31+
}
32+
33+
pub async fn oneoff_async_connection() -> anyhow::Result<AsyncPgConnection> {
34+
let config = config::DatabasePools::full_from_environment(&config::Base::from_environment()?)?;
35+
Ok(oneoff_async_connection_with_config(&config).await?)
36+
}
37+
2638
pub fn connection_url(config: &config::DatabasePools, url: &str) -> String {
2739
let mut url = Url::parse(url).expect("Invalid database URL");
2840

0 commit comments

Comments
 (0)