Skip to content

Commit dd66a73

Browse files
committed
invalidate CDN in more build error cases, & invalidate after yank / create-delete
1 parent 802fd8e commit dd66a73

File tree

5 files changed

+95
-60
lines changed

5 files changed

+95
-60
lines changed

src/bin/cratesfyi.rs

+1
Original file line numberDiff line numberDiff line change
@@ -606,6 +606,7 @@ impl Context for BinContext {
606606
self.pool()?,
607607
self.metrics()?,
608608
self.config()?,
609+
self.cdn()?,
609610
self.storage()?,
610611
);
611612
fn storage(self) -> Storage = Storage::new(

src/build_queue.rs

+76
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::cdn::{self, CdnBackend};
12
use crate::db::{delete_crate, Pool};
23
use crate::docbuilder::PackageKind;
34
use crate::error::Result;
@@ -27,6 +28,7 @@ pub(crate) struct QueuedCrate {
2728
#[derive(Debug)]
2829
pub struct BuildQueue {
2930
config: Arc<Config>,
31+
cdn: Arc<CdnBackend>,
3032
storage: Arc<Storage>,
3133
pub(crate) db: Pool,
3234
metrics: Arc<Metrics>,
@@ -38,11 +40,13 @@ impl BuildQueue {
3840
db: Pool,
3941
metrics: Arc<Metrics>,
4042
config: Arc<Config>,
43+
cdn: Arc<CdnBackend>,
4144
storage: Arc<Storage>,
4245
) -> Self {
4346
BuildQueue {
4447
max_attempts: config.build_attempts.into(),
4548
config,
49+
cdn,
4650
db,
4751
metrics,
4852
storage,
@@ -173,6 +177,10 @@ impl BuildQueue {
173177
)
174178
});
175179
self.metrics.total_builds.inc();
180+
if let Err(err) = cdn::invalidate_crate(&self.config, &self.cdn, &to_process.name) {
181+
report_error(&err);
182+
}
183+
176184
match res {
177185
Ok(()) => {
178186
transaction.execute("DELETE FROM queue WHERE id = $1;", &[&to_process.id])?;
@@ -284,6 +292,10 @@ impl BuildQueue {
284292
Ok(_) => debug!("{}-{} yanked", release.name, release.version),
285293
Err(err) => report_error(&err),
286294
}
295+
if let Err(err) = cdn::invalidate_crate(&self.config, &self.cdn, &release.name)
296+
{
297+
report_error(&err);
298+
}
287299
}
288300

289301
Change::Added(release) => {
@@ -319,6 +331,9 @@ impl BuildQueue {
319331
Ok(_) => info!("crate {} was deleted from the index and will be deleted from the database", krate),
320332
Err(err) => report_error(&err),
321333
}
334+
if let Err(err) = cdn::invalidate_crate(&self.config, &self.cdn, krate) {
335+
report_error(&err);
336+
}
322337
}
323338
}
324339
}
@@ -520,6 +535,67 @@ mod tests {
520535
assert_eq!(metrics.total_builds.get(), 9);
521536
assert_eq!(metrics.failed_builds.get(), 1);
522537

538+
// no invalidations were run since we don't have a distribution id configured
539+
assert!(matches!(*env.cdn(), CdnBackend::Dummy(_)));
540+
if let CdnBackend::Dummy(ref invalidation_requests) = *env.cdn() {
541+
let ir = invalidation_requests.lock().unwrap();
542+
assert!(ir.is_empty());
543+
}
544+
545+
Ok(())
546+
})
547+
}
548+
549+
#[test]
550+
fn test_invalidate_cdn_after_build_and_error() {
551+
crate::test::wrapper(|env| {
552+
env.override_config(|config| {
553+
config.cloudfront_distribution_id_web = Some("distribution_id".into());
554+
});
555+
556+
let queue = env.build_queue();
557+
558+
queue.add_crate("will_succeed", "1.0.0", -1, None)?;
559+
queue.add_crate("will_fail", "1.0.0", 0, None)?;
560+
561+
assert!(matches!(*env.cdn(), CdnBackend::Dummy(_)));
562+
if let CdnBackend::Dummy(ref invalidation_requests) = *env.cdn() {
563+
let ir = invalidation_requests.lock().unwrap();
564+
assert!(ir.is_empty());
565+
}
566+
567+
queue.process_next_crate(|krate| {
568+
assert_eq!("will_succeed", krate.name);
569+
Ok(())
570+
})?;
571+
if let CdnBackend::Dummy(ref invalidation_requests) = *env.cdn() {
572+
let ir = invalidation_requests.lock().unwrap();
573+
assert_eq!(
574+
*ir,
575+
[
576+
("distribution_id".into(), "/will_succeed*".into()),
577+
("distribution_id".into(), "/crate/will_succeed*".into()),
578+
]
579+
);
580+
}
581+
582+
queue.process_next_crate(|krate| {
583+
assert_eq!("will_fail", krate.name);
584+
anyhow::bail!("simulate a failure");
585+
})?;
586+
if let CdnBackend::Dummy(ref invalidation_requests) = *env.cdn() {
587+
let ir = invalidation_requests.lock().unwrap();
588+
assert_eq!(
589+
*ir,
590+
[
591+
("distribution_id".into(), "/will_succeed*".into()),
592+
("distribution_id".into(), "/crate/will_succeed*".into()),
593+
("distribution_id".into(), "/will_fail*".into()),
594+
("distribution_id".into(), "/crate/will_fail*".into()),
595+
]
596+
);
597+
}
598+
523599
Ok(())
524600
})
525601
}

src/cdn.rs

+14-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::Config;
2-
use anyhow::{Error, Result};
2+
use anyhow::{Context, Error, Result};
33
use aws_sdk_cloudfront::{
44
model::{InvalidationBatch, Paths},
55
Client, RetryConfig,
@@ -18,6 +18,7 @@ pub(crate) enum CdnKind {
1818
CloudFront,
1919
}
2020

21+
#[derive(Debug)]
2122
pub enum CdnBackend {
2223
Dummy(Arc<Mutex<Vec<(String, String)>>>),
2324
CloudFront {
@@ -116,6 +117,18 @@ impl CdnBackend {
116117
}
117118
}
118119

120+
pub(crate) fn invalidate_crate(config: &Config, cdn: &CdnBackend, name: &str) -> Result<()> {
121+
if let Some(distribution_id) = config.cloudfront_distribution_id_web.as_ref() {
122+
cdn.create_invalidation(
123+
distribution_id,
124+
&[&format!("/{}*", name), &format!("/crate/{}*", name)],
125+
)
126+
.context("error creating CDN invalidation")?;
127+
}
128+
129+
Ok(())
130+
}
131+
119132
#[cfg(test)]
120133
mod tests {
121134
use super::*;

src/docbuilder/rustwide_builder.rs

+3-59
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use crate::cdn::CdnBackend;
21
use crate::db::file::add_path_into_database;
32
use crate::db::{
43
add_build_into_database, add_doc_coverage, add_package_into_database,
@@ -10,12 +9,11 @@ use crate::index::api::ReleaseData;
109
use crate::repositories::RepositoryStatsUpdater;
1110
use crate::storage::{rustdoc_archive_path, source_archive_path};
1211
use crate::utils::{
13-
copy_dir_all, parse_rustc_version, queue_builder, report_error, set_config, CargoMetadata,
14-
ConfigName,
12+
copy_dir_all, parse_rustc_version, queue_builder, set_config, CargoMetadata, ConfigName,
1513
};
1614
use crate::{db::blacklist::is_blacklisted, utils::MetadataPackage};
1715
use crate::{Config, Context, Index, Metrics, Storage};
18-
use anyhow::{anyhow, bail, Context as _, Error};
16+
use anyhow::{anyhow, bail, Error};
1917
use docsrs_metadata::{Metadata, DEFAULT_TARGETS, HOST_TARGET};
2018
use failure::Error as FailureError;
2119
use log::{debug, info, warn, LevelFilter};
@@ -44,7 +42,6 @@ pub struct RustwideBuilder {
4442
config: Arc<Config>,
4543
db: Pool,
4644
storage: Arc<Storage>,
47-
cdn: Arc<CdnBackend>,
4845
metrics: Arc<Metrics>,
4946
index: Arc<Index>,
5047
rustc_version: String,
@@ -83,7 +80,6 @@ impl RustwideBuilder {
8380
config,
8481
db: context.pool()?,
8582
storage: context.storage()?,
86-
cdn: context.cdn()?,
8783
metrics: context.metrics()?,
8884
index: context.index()?,
8985
rustc_version: String::new(),
@@ -504,18 +500,6 @@ impl RustwideBuilder {
504500
.purge_from_cache(&self.workspace)
505501
.map_err(FailureError::compat)?;
506502
local_storage.close()?;
507-
if let Some(distribution_id) = self.config.cloudfront_distribution_id_web.as_ref() {
508-
if let Err(err) = self
509-
.cdn
510-
.create_invalidation(
511-
distribution_id,
512-
&[&format!("/{}*", name), &format!("/crate/{}*", name)],
513-
)
514-
.context("error creating CDN invalidation")
515-
{
516-
report_error(&err);
517-
}
518-
}
519503
Ok(successful)
520504
}
521505

@@ -822,10 +806,7 @@ pub(crate) struct BuildResult {
822806
#[cfg(test)]
823807
mod tests {
824808
use super::*;
825-
use crate::{
826-
cdn::CdnKind,
827-
test::{assert_redirect, assert_success, wrapper},
828-
};
809+
use crate::test::{assert_redirect, assert_success, wrapper};
829810
use serde_json::Value;
830811

831812
#[test]
@@ -942,12 +923,6 @@ mod tests {
942923
}
943924
}
944925

945-
assert!(matches!(*env.cdn(), CdnBackend::Dummy(_)));
946-
if let CdnBackend::Dummy(ref invalidation_requests) = *env.cdn() {
947-
let ir = invalidation_requests.lock().unwrap();
948-
assert!(ir.is_empty());
949-
}
950-
951926
Ok(())
952927
})
953928
}
@@ -1069,37 +1044,6 @@ mod tests {
10691044
});
10701045
}
10711046

1072-
#[test]
1073-
#[ignore]
1074-
fn test_cdn_invalidation() {
1075-
wrapper(|env| {
1076-
env.override_config(|cfg| {
1077-
cfg.cdn_backend = CdnKind::Dummy;
1078-
cfg.cloudfront_distribution_id_web = Some("distribution_id".into());
1079-
});
1080-
1081-
let mut builder = RustwideBuilder::init(env).unwrap();
1082-
assert!(builder.build_package(
1083-
DUMMY_CRATE_NAME,
1084-
DUMMY_CRATE_VERSION,
1085-
PackageKind::CratesIo
1086-
)?);
1087-
1088-
assert!(matches!(*env.cdn(), CdnBackend::Dummy(_)));
1089-
if let CdnBackend::Dummy(ref invalidation_requests) = *env.cdn() {
1090-
let ir = invalidation_requests.lock().unwrap();
1091-
assert_eq!(ir.len(), 2);
1092-
assert_eq!(ir[0], ("distribution_id".into(), "/empty-library*".into()));
1093-
assert_eq!(
1094-
ir[1],
1095-
("distribution_id".into(), "/crate/empty-library*".into())
1096-
);
1097-
}
1098-
1099-
Ok(())
1100-
});
1101-
}
1102-
11031047
#[test]
11041048
#[ignore]
11051049
fn test_locked_fails_unlocked_needs_new_deps() {

src/test/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,7 @@ impl TestEnvironment {
292292
self.db().pool(),
293293
self.metrics(),
294294
self.config(),
295+
self.cdn(),
295296
self.storage(),
296297
))
297298
})

0 commit comments

Comments
 (0)