Skip to content

Commit 25702f1

Browse files
Add RepositoryStatsUpdater instance to global contexts so they can be used in CrateDetails
1 parent 13f4d8c commit 25702f1

File tree

11 files changed

+180
-75
lines changed

11 files changed

+180
-75
lines changed

src/bin/cratesfyi.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -423,11 +423,15 @@ impl DatabaseSubcommand {
423423
}
424424

425425
Self::UpdateRepositoryFields => {
426-
RepositoryStatsUpdater::update_all_crates(&ctx.config()?, &ctx.pool()?)?;
426+
let config = ctx.config()?;
427+
let updater = RepositoryStatsUpdater::new(&config);
428+
updater.update_all_crates(&ctx.pool()?)?;
427429
}
428430

429431
Self::BackfillRepositoryStats => {
430-
RepositoryStatsUpdater::backfill_repositories(&ctx)?;
432+
let config = ctx.config()?;
433+
let updater = RepositoryStatsUpdater::new(&config);
434+
updater.backfill_repositories(&ctx)?;
431435
}
432436

433437
Self::UpdateCrateRegistryFields { name } => {
@@ -532,6 +536,7 @@ struct BinContext {
532536
pool: OnceCell<Pool>,
533537
metrics: OnceCell<Arc<Metrics>>,
534538
index: OnceCell<Arc<Index>>,
539+
repository_stats_updater: OnceCell<Arc<RepositoryStatsUpdater>>,
535540
}
536541

537542
impl BinContext {
@@ -543,6 +548,7 @@ impl BinContext {
543548
pool: OnceCell::new(),
544549
metrics: OnceCell::new(),
545550
index: OnceCell::new(),
551+
repository_stats_updater: OnceCell::new(),
546552
}
547553
}
548554

@@ -614,4 +620,14 @@ impl Context for BinContext {
614620
})?
615621
.clone())
616622
}
623+
624+
fn repository_stats_updater(&self) -> Result<Arc<RepositoryStatsUpdater>, Error> {
625+
Ok(self
626+
.repository_stats_updater
627+
.get_or_try_init::<_, Error>(|| {
628+
let config = self.config()?;
629+
Ok(Arc::new(RepositoryStatsUpdater::new(&config)))
630+
})?
631+
.clone())
632+
}
617633
}

src/context.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::db::Pool;
2+
use crate::repositories::RepositoryStatsUpdater;
23
use crate::{BuildQueue, Config, Index, Metrics, Storage};
34
use failure::Error;
45
use std::sync::Arc;
@@ -10,4 +11,5 @@ pub trait Context {
1011
fn pool(&self) -> Result<Pool, Error>;
1112
fn metrics(&self) -> Result<Arc<Metrics>, Error>;
1213
fn index(&self) -> Result<Arc<Index>, Error>;
14+
fn repository_stats_updater(&self) -> Result<Arc<RepositoryStatsUpdater>, Error>;
1315
}

src/docbuilder/rustwide_builder.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ pub struct RustwideBuilder {
4343
metrics: Arc<Metrics>,
4444
index: Arc<Index>,
4545
rustc_version: String,
46+
repository_stats_updater: Arc<RepositoryStatsUpdater>,
4647
skip_build_if_exists: bool,
4748
}
4849

@@ -73,6 +74,7 @@ impl RustwideBuilder {
7374
metrics: context.metrics()?,
7475
index: context.index()?,
7576
rustc_version: String::new(),
77+
repository_stats_updater: context.repository_stats_updater()?,
7678
skip_build_if_exists: false,
7779
})
7880
}
@@ -653,7 +655,8 @@ impl RustwideBuilder {
653655
}
654656

655657
fn get_repo(&self, conn: &mut Client, metadata: &MetadataPackage) -> Result<Option<i32>> {
656-
RepositoryStatsUpdater::load_repository(conn, metadata, self.config.clone())
658+
self.repository_stats_updater
659+
.load_repository(conn, metadata)
657660
}
658661
}
659662

src/repositories/github.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ use reqwest::{
77
header::{HeaderMap, HeaderValue, ACCEPT, AUTHORIZATION, USER_AGENT},
88
};
99
use serde::Deserialize;
10-
use std::sync::Arc;
1110

1211
use crate::repositories::{
1312
FetchRepositoriesResult, Repository, RepositoryForge, RepositoryName, APP_USER_AGENT,
@@ -50,7 +49,7 @@ pub struct GitHub {
5049
impl GitHub {
5150
/// Returns `Err` if the access token has invalid syntax (but *not* if it isn't authorized).
5251
/// Returns `Ok(None)` if there is no access token.
53-
pub fn new(config: &Arc<Config>) -> Result<Option<Self>> {
52+
pub fn new(config: &Config) -> Result<Option<Self>> {
5453
let mut headers = HeaderMap::new();
5554
headers.insert(USER_AGENT, HeaderValue::from_static(APP_USER_AGENT));
5655
headers.insert(ACCEPT, HeaderValue::from_static("application/json"));
@@ -79,7 +78,7 @@ impl RepositoryForge for GitHub {
7978
"github.com"
8079
}
8180

82-
fn icon(&self) -> &str {
81+
fn icon(&self) -> &'static str {
8382
"github"
8483
}
8584

src/repositories/gitlab.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ impl RepositoryForge for GitLab {
7171
self.host
7272
}
7373

74-
fn icon(&self) -> &str {
74+
fn icon(&self) -> &'static str {
7575
"gitlab"
7676
}
7777

src/repositories/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ pub use self::github::GitHub;
22
pub use self::gitlab::GitLab;
33
pub(crate) use self::updater::RepositoryName;
44
pub use self::updater::{
5-
get_icon_name, FetchRepositoriesResult, Repository, RepositoryForge, RepositoryStatsUpdater,
5+
FetchRepositoriesResult, Repository, RepositoryForge, RepositoryStatsUpdater,
66
};
77

88
pub const APP_USER_AGENT: &str = concat!(

src/repositories/updater.rs

Lines changed: 38 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use once_cell::sync::Lazy;
88
use postgres::Client;
99
use regex::Regex;
1010
use std::collections::{HashMap, HashSet};
11+
use std::fmt;
1112
use std::sync::Arc;
1213
use std::time::Duration;
1314

@@ -17,7 +18,7 @@ pub trait RepositoryForge {
1718
fn host(&self) -> &str;
1819

1920
/// FontAwesome icon used in the front-end.
20-
fn icon(&self) -> &str;
21+
fn icon(&self) -> &'static str;
2122

2223
/// How many items we can query in one graphql request.
2324
fn chunk_size(&self) -> usize;
@@ -49,11 +50,23 @@ pub struct FetchRepositoriesResult {
4950
pub missing: Vec<String>,
5051
}
5152

52-
pub struct RepositoryStatsUpdater;
53+
pub struct RepositoryStatsUpdater {
54+
updaters: Vec<Box<dyn RepositoryForge + Send + Sync>>,
55+
}
56+
57+
impl fmt::Debug for RepositoryStatsUpdater {
58+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
59+
write!(
60+
f,
61+
"RepositoryStatsUpdater {{ {:?} }}",
62+
self.updaters.iter().map(|u| u.host()).collect::<Vec<_>>()
63+
)
64+
}
65+
}
5366

5467
impl RepositoryStatsUpdater {
55-
fn get_updaters(config: &Arc<Config>) -> Vec<Box<dyn RepositoryForge>> {
56-
let mut updaters: Vec<Box<dyn RepositoryForge>> = Vec::with_capacity(3);
68+
pub fn new(config: &Config) -> Self {
69+
let mut updaters: Vec<Box<dyn RepositoryForge + Send + Sync>> = Vec::with_capacity(3);
5770
if let Ok(Some(updater)) = GitHub::new(&config) {
5871
updaters.push(Box::new(updater));
5972
}
@@ -63,15 +76,13 @@ impl RepositoryStatsUpdater {
6376
if let Ok(Some(updater)) = GitLab::new("gitlab.freedesktop.org", &None) {
6477
updaters.push(Box::new(updater));
6578
}
66-
updaters
79+
Self { updaters }
6780
}
68-
}
6981

70-
impl RepositoryStatsUpdater {
7182
pub(crate) fn load_repository(
83+
&self,
7284
conn: &mut Client,
7385
metadata: &MetadataPackage,
74-
config: Arc<Config>,
7586
) -> Result<Option<i32>> {
7687
let url = match &metadata.repository {
7788
Some(url) => url,
@@ -80,16 +91,10 @@ impl RepositoryStatsUpdater {
8091
return Ok(None);
8192
}
8293
};
83-
let updaters = Self::get_updaters(&config);
84-
85-
Self::load_repository_inner(conn, url, &updaters)
94+
self.load_repository_inner(conn, url)
8695
}
8796

88-
fn load_repository_inner(
89-
conn: &mut Client,
90-
url: &str,
91-
updaters: &[Box<dyn RepositoryForge>],
92-
) -> Result<Option<i32>> {
97+
fn load_repository_inner(&self, conn: &mut Client, url: &str) -> Result<Option<i32>> {
9398
let name = match repository_name(url) {
9499
Some(name) => name,
95100
None => return Ok(None),
@@ -102,7 +107,7 @@ impl RepositoryStatsUpdater {
102107
)? {
103108
return Ok(Some(row.get("id")));
104109
}
105-
for updater in updaters.iter().filter(|u| u.host() == name.host) {
110+
for updater in self.updaters.iter().filter(|u| u.host() == name.host) {
106111
let res = match updater.fetch_repository(&name) {
107112
Ok(Some(repo)) => Self::store_repository(conn, updater.host(), repo),
108113
Err(err) => {
@@ -124,22 +129,19 @@ impl RepositoryStatsUpdater {
124129
}
125130

126131
pub fn start_crons(config: Arc<Config>, pool: Pool) -> Result<()> {
132+
let instance = Self::new(&config);
127133
cron(
128134
"repositories stats updater",
129135
Duration::from_secs(60 * 60),
130-
move || {
131-
Self::update_all_crates(&config, &pool)?;
132-
Ok(())
133-
},
136+
move || instance.update_all_crates(&pool),
134137
)?;
135138

136139
Ok(())
137140
}
138141

139-
pub fn update_all_crates(config: &Arc<Config>, pool: &Pool) -> Result<()> {
142+
pub fn update_all_crates(&self, pool: &Pool) -> Result<()> {
140143
let mut conn = pool.get()?;
141-
let updaters = Self::get_updaters(config);
142-
for updater in updaters {
144+
for updater in &self.updaters {
143145
info!("started updating `{}` repositories stats", updater.host());
144146

145147
let needs_update = conn
@@ -174,11 +176,10 @@ impl RepositoryStatsUpdater {
174176
Ok(())
175177
}
176178

177-
pub fn backfill_repositories(ctx: &dyn Context) -> Result<()> {
179+
pub fn backfill_repositories(&self, ctx: &dyn Context) -> Result<()> {
178180
let pool = ctx.pool()?;
179181
let mut conn = pool.get()?;
180-
let updaters = Self::get_updaters(&ctx.config()?);
181-
for updater in updaters.iter() {
182+
for updater in &self.updaters {
182183
info!(
183184
"started backfilling `{}` repositories stats",
184185
updater.host()
@@ -201,9 +202,7 @@ impl RepositoryStatsUpdater {
201202

202203
if missing_urls.contains(&url) {
203204
debug!("{} {} points to a known missing repo", name, version);
204-
} else if let Some(node_id) =
205-
Self::load_repository_inner(&mut conn, &url, &updaters)?
206-
{
205+
} else if let Some(node_id) = self.load_repository_inner(&mut conn, &url)? {
207206
conn.execute(
208207
"UPDATE releases SET repository_id = $1 WHERE id = $2;",
209208
&[&node_id, &id],
@@ -229,6 +228,15 @@ impl RepositoryStatsUpdater {
229228
Ok(())
230229
}
231230

231+
pub fn get_icon_name(&self, host: &str) -> &'static str {
232+
for updater in &self.updaters {
233+
if updater.host() == host {
234+
return updater.icon();
235+
}
236+
}
237+
""
238+
}
239+
232240
fn store_repository(conn: &mut Client, host: &str, repo: Repository) -> Result<i32> {
233241
trace!(
234242
"storing {} repository stats for {}",
@@ -300,20 +308,6 @@ pub struct RepositoryName<'a> {
300308
pub host: &'a str,
301309
}
302310

303-
pub fn get_icon_name(host: &str) -> &'static str {
304-
// macro_rules! return_if_true {
305-
// ($t:ty, $icon:expr) => {
306-
// if <$t>::hosts().iter().any(|&h| h == host) {
307-
// return $icon;
308-
// }
309-
// };
310-
// }
311-
312-
// return_if_true!(GitHub, "github");
313-
// return_if_true!(GitLab, "gitlab");
314-
""
315-
}
316-
317311
#[cfg(test)]
318312
mod test {
319313
use super::*;
@@ -347,8 +341,6 @@ mod test {
347341
assert_name!("https://gitlab.freedesktop.org/test/test" => (
348342
"test", "test", "gitlab.freedesktop.org"
349343
));
350-
assert_name!("https://www.github.com/onur/cratesfyi" => None);
351-
assert_name!("https://github.com/onur/cratesfyi" => None);
352344

353345
// github checks
354346
assert_name!("https://github.com/onur/cratesfyi" => ("onur", "cratesfyi", "github.com"));
@@ -358,8 +350,5 @@ mod test {
358350
assert_name!("https://github.com/onur23cmD_M_R_L_/crates_fy-i" => (
359351
"onur23cmD_M_R_L_", "crates_fy-i", "github.com"
360352
));
361-
assert_name!("https://www.github.com/onur/cratesfyi" => None);
362-
assert_name!("http://www.github.com/onur/cratesfyi" => None);
363-
assert_name!("http://www.gitlab.com/onur/cratesfyi" => None);
364353
}
365354
}

0 commit comments

Comments
 (0)