Skip to content

Commit 7884227

Browse files
authored
Merge pull request #5066 from arlosi/db-index
Generate index metadata files from the database
2 parents 25caa95 + f669528 commit 7884227

24 files changed

+462
-22
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cargo-registry-index/Cargo.toml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,18 @@ edition = "2021"
1010
path = "lib.rs"
1111

1212
[features]
13-
testing = ["serde_json"]
13+
testing = []
1414

1515
[dependencies]
1616
anyhow = "=1.0.70"
1717
base64 = "=0.13.1"
1818
dotenv = "=0.15.0"
1919
git2 = "=0.17.1"
2020
serde = { version = "=1.0.160", features = ["derive"] }
21+
serde_json = "=1.0.96"
2122
tempfile = "=3.5.0"
2223
tracing = "=0.1.37"
2324
url = "=2.3.1"
24-
serde_json = { version = "=1.0.96", optional = true }
25+
26+
[dev-dependencies]
27+
claims = "=0.7.1"

cargo-registry-index/lib.rs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,21 @@ pub struct Crate {
148148
pub v: Option<u32>,
149149
}
150150

151+
impl Crate {
152+
pub fn write_to<W: Write>(&self, mut writer: W) -> anyhow::Result<()> {
153+
serde_json::to_writer(&mut writer, self)?;
154+
writer.write_all(b"\n")?;
155+
Ok(())
156+
}
157+
}
158+
159+
pub fn write_crates<W: Write>(crates: &[Crate], mut writer: W) -> anyhow::Result<()> {
160+
for krate in crates {
161+
krate.write_to(&mut writer)?;
162+
}
163+
Ok(())
164+
}
165+
151166
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
152167
pub struct Dependency {
153168
pub name: String,
@@ -595,3 +610,57 @@ pub fn run_via_cli(command: &mut Command, credentials: &Credentials) -> anyhow::
595610

596611
Ok(())
597612
}
613+
614+
#[cfg(test)]
615+
mod tests {
616+
use super::*;
617+
use claims::*;
618+
619+
#[test]
620+
fn crate_writer() {
621+
let krate = Crate {
622+
name: "foo".to_string(),
623+
vers: "1.2.3".to_string(),
624+
deps: vec![],
625+
cksum: "0123456789asbcdef".to_string(),
626+
features: Default::default(),
627+
features2: None,
628+
yanked: None,
629+
links: None,
630+
v: None,
631+
};
632+
let mut buffer = Vec::new();
633+
assert_ok!(krate.write_to(&mut buffer));
634+
assert_ok_eq!(String::from_utf8(buffer), "\
635+
{\"name\":\"foo\",\"vers\":\"1.2.3\",\"deps\":[],\"cksum\":\"0123456789asbcdef\",\"features\":{},\"yanked\":null}\n\
636+
");
637+
}
638+
639+
#[test]
640+
fn test_write_crates() {
641+
let versions = vec!["0.1.0", "1.0.0-beta.1", "1.0.0", "1.2.3"];
642+
let crates = versions
643+
.into_iter()
644+
.map(|vers| Crate {
645+
name: "foo".to_string(),
646+
vers: vers.to_string(),
647+
deps: vec![],
648+
cksum: "0123456789asbcdef".to_string(),
649+
features: Default::default(),
650+
features2: None,
651+
yanked: None,
652+
links: None,
653+
v: None,
654+
})
655+
.collect::<Vec<_>>();
656+
657+
let mut buffer = Vec::new();
658+
assert_ok!(write_crates(&crates, &mut buffer));
659+
assert_ok_eq!(String::from_utf8(buffer), "\
660+
{\"name\":\"foo\",\"vers\":\"0.1.0\",\"deps\":[],\"cksum\":\"0123456789asbcdef\",\"features\":{},\"yanked\":null}\n\
661+
{\"name\":\"foo\",\"vers\":\"1.0.0-beta.1\",\"deps\":[],\"cksum\":\"0123456789asbcdef\",\"features\":{},\"yanked\":null}\n\
662+
{\"name\":\"foo\",\"vers\":\"1.0.0\",\"deps\":[],\"cksum\":\"0123456789asbcdef\",\"features\":{},\"yanked\":null}\n\
663+
{\"name\":\"foo\",\"vers\":\"1.2.3\",\"deps\":[],\"cksum\":\"0123456789asbcdef\",\"features\":{},\"yanked\":null}\n\
664+
");
665+
}
666+
}

src/admin/delete_crate.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::background_jobs::Job;
12
use crate::{admin::dialoguer, config, db, models::Crate, schema::crates};
23

34
use diesel::prelude::*;
@@ -54,5 +55,9 @@ fn delete(opts: Opts, conn: &mut PgConnection) {
5455
panic!("aborting transaction");
5556
}
5657

57-
uploader.delete_index(&client, &krate.name).unwrap();
58+
if dotenv::var("FEATURE_INDEX_SYNC").is_ok() {
59+
Job::enqueue_sync_to_index(&krate.name, conn).unwrap();
60+
} else {
61+
uploader.delete_index(&client, &krate.name).unwrap();
62+
}
5863
}

src/admin/delete_version.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::background_jobs::Job;
12
use crate::{
23
admin::dialoguer,
34
db,
@@ -57,4 +58,8 @@ fn delete(opts: Opts, conn: &mut PgConnection) {
5758
if !opts.yes && !dialoguer::confirm("commit?") {
5859
panic!("aborting transaction");
5960
}
61+
62+
if dotenv::var("FEATURE_INDEX_SYNC").is_ok() {
63+
Job::enqueue_sync_to_index(&krate.name, conn).unwrap();
64+
}
6065
}

src/admin/yank_version.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use crate::{
55
schema::versions,
66
};
77

8+
use crate::background_jobs::Job;
89
use diesel::prelude::*;
910

1011
#[derive(clap::Parser, Debug)]
@@ -64,7 +65,11 @@ fn yank(opts: Opts, conn: &mut PgConnection) {
6465
.execute(conn)
6566
.unwrap();
6667

67-
crate::worker::sync_yanked(krate.name, v.num)
68-
.enqueue(conn)
69-
.unwrap();
68+
if dotenv::var("FEATURE_INDEX_SYNC").is_ok() {
69+
Job::enqueue_sync_to_index(&krate.name, conn).unwrap();
70+
} else {
71+
crate::worker::sync_yanked(krate.name, v.num)
72+
.enqueue(conn)
73+
.unwrap();
74+
}
7075
}

src/background_jobs.rs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ pub enum Job {
1818
IndexAddCrate(IndexAddCrateJob),
1919
IndexSquash,
2020
IndexSyncToHttp(IndexSyncToHttpJob),
21+
SyncToGitIndex(SyncToIndexJob),
22+
SyncToSparseIndex(SyncToIndexJob),
2123
IndexUpdateYanked(IndexUpdateYankedJob),
2224
NormalizeIndex(NormalizeIndexJob),
2325
RenderAndUploadReadme(RenderAndUploadReadmeJob),
@@ -47,8 +49,47 @@ impl Job {
4749
const INDEX_UPDATE_YANKED: &str = "sync_yanked";
4850
const NORMALIZE_INDEX: &str = "normalize_index";
4951
const RENDER_AND_UPLOAD_README: &str = "render_and_upload_readme";
52+
const SYNC_TO_GIT_INDEX: &str = "sync_to_git_index";
53+
const SYNC_TO_SPARSE_INDEX: &str = "sync_to_sparse_index";
5054
const UPDATE_DOWNLOADS: &str = "update_downloads";
5155

56+
pub fn enqueue_sync_to_index<T: ToString>(
57+
krate: T,
58+
conn: &mut PgConnection,
59+
) -> Result<(), EnqueueError> {
60+
use crate::schema::background_jobs::dsl::*;
61+
62+
let to_git = Self::sync_to_git_index(krate.to_string());
63+
let to_git = (
64+
job_type.eq(to_git.as_type_str()),
65+
data.eq(to_git.to_value()?),
66+
);
67+
68+
let to_sparse = Self::sync_to_sparse_index(krate.to_string());
69+
let to_sparse = (
70+
job_type.eq(to_sparse.as_type_str()),
71+
data.eq(to_sparse.to_value()?),
72+
);
73+
74+
diesel::insert_into(background_jobs)
75+
.values(vec![to_git, to_sparse])
76+
.execute(conn)?;
77+
78+
Ok(())
79+
}
80+
81+
pub fn sync_to_git_index<T: ToString>(krate: T) -> Job {
82+
Job::SyncToGitIndex(SyncToIndexJob {
83+
krate: krate.to_string(),
84+
})
85+
}
86+
87+
pub fn sync_to_sparse_index<T: ToString>(krate: T) -> Job {
88+
Job::SyncToSparseIndex(SyncToIndexJob {
89+
krate: krate.to_string(),
90+
})
91+
}
92+
5293
fn as_type_str(&self) -> &'static str {
5394
match self {
5495
Job::DailyDbMaintenance => Self::DAILY_DB_MAINTENANCE,
@@ -59,6 +100,8 @@ impl Job {
59100
Job::IndexUpdateYanked(_) => Self::INDEX_UPDATE_YANKED,
60101
Job::NormalizeIndex(_) => Self::NORMALIZE_INDEX,
61102
Job::RenderAndUploadReadme(_) => Self::RENDER_AND_UPLOAD_README,
103+
Job::SyncToGitIndex(_) => Self::SYNC_TO_GIT_INDEX,
104+
Job::SyncToSparseIndex(_) => Self::SYNC_TO_SPARSE_INDEX,
62105
Job::UpdateDownloads => Self::UPDATE_DOWNLOADS,
63106
}
64107
}
@@ -73,6 +116,8 @@ impl Job {
73116
Job::IndexUpdateYanked(inner) => serde_json::to_value(inner),
74117
Job::NormalizeIndex(inner) => serde_json::to_value(inner),
75118
Job::RenderAndUploadReadme(inner) => serde_json::to_value(inner),
119+
Job::SyncToGitIndex(inner) => serde_json::to_value(inner),
120+
Job::SyncToSparseIndex(inner) => serde_json::to_value(inner),
76121
Job::UpdateDownloads => Ok(serde_json::Value::Null),
77122
}
78123
}
@@ -101,6 +146,8 @@ impl Job {
101146
Self::INDEX_UPDATE_YANKED => Job::IndexUpdateYanked(from_value(value)?),
102147
Self::NORMALIZE_INDEX => Job::NormalizeIndex(from_value(value)?),
103148
Self::RENDER_AND_UPLOAD_README => Job::RenderAndUploadReadme(from_value(value)?),
149+
Self::SYNC_TO_GIT_INDEX => Job::SyncToGitIndex(from_value(value)?),
150+
Self::SYNC_TO_SPARSE_INDEX => Job::SyncToSparseIndex(from_value(value)?),
104151
Self::UPDATE_DOWNLOADS => Job::UpdateDownloads,
105152
job_type => Err(PerformError::from(format!("Unknown job type {job_type}")))?,
106153
})
@@ -136,6 +183,8 @@ impl Job {
136183
args.base_url.as_deref(),
137184
args.pkg_path_in_vcs.as_deref(),
138185
),
186+
Job::SyncToGitIndex(args) => worker::sync_to_git_index(env, conn, &args.krate),
187+
Job::SyncToSparseIndex(args) => worker::sync_to_sparse_index(env, conn, &args.krate),
139188
Job::UpdateDownloads => worker::perform_update_downloads(&mut *fresh_connection(pool)?),
140189
}
141190
}
@@ -172,6 +221,11 @@ pub struct IndexSyncToHttpJob {
172221
pub(super) crate_name: String,
173222
}
174223

224+
#[derive(Serialize, Deserialize)]
225+
pub struct SyncToIndexJob {
226+
pub(super) krate: String,
227+
}
228+
175229
#[derive(Serialize, Deserialize)]
176230
pub struct IndexUpdateYankedJob {
177231
pub(super) krate: String,

src/config.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ pub struct Server {
4747
pub version_id_cache_ttl: Duration,
4848
pub cdn_user_agent: String,
4949
pub balance_capacity: BalanceCapacityConfig,
50+
pub feature_index_sync: bool,
5051
}
5152

5253
impl Default for Server {
@@ -151,6 +152,7 @@ impl Default for Server {
151152
cdn_user_agent: dotenv::var("WEB_CDN_USER_AGENT")
152153
.unwrap_or_else(|_| "Amazon CloudFront".into()),
153154
balance_capacity: BalanceCapacityConfig::from_environment(),
155+
feature_index_sync: dotenv::var("FEATURE_INDEX_SYNC").is_ok(),
154156
}
155157
}
156158
}

src/controllers/krate/publish.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! Functionality related to publishing a new crate or version of a crate.
22
33
use crate::auth::AuthCheck;
4+
use crate::background_jobs::Job;
45
use axum::body::Bytes;
56
use flate2::read::GzDecoder;
67
use hex::ToHex;
@@ -271,7 +272,12 @@ pub async fn publish(app: AppState, req: BytesRequest) -> AppResult<Json<GoodCra
271272
links,
272273
v,
273274
};
274-
worker::add_crate(git_crate).enqueue(conn)?;
275+
276+
if app.config.feature_index_sync {
277+
Job::enqueue_sync_to_index(&krate.name, conn)?;
278+
} else {
279+
worker::add_crate(git_crate).enqueue(conn)?;
280+
}
275281

276282
// The `other` field on `PublishWarnings` was introduced to handle a temporary warning
277283
// that is no longer needed. As such, crates.io currently does not return any `other`

src/controllers/version/yank.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! Endpoints for yanking and unyanking specific versions of crates
22
33
use crate::auth::AuthCheck;
4+
use crate::background_jobs::Job;
45

56
use super::version_and_crate;
67
use crate::controllers::cargo_prelude::*;
@@ -84,7 +85,11 @@ fn modify_yank(
8485

8586
insert_version_owner_action(conn, version.id, user.id, api_token_id, action)?;
8687

87-
worker::sync_yanked(krate.name, version.num).enqueue(conn)?;
88+
if state.config.feature_index_sync {
89+
Job::enqueue_sync_to_index(&krate.name, conn)?;
90+
} else {
91+
worker::sync_yanked(krate.name, version.num).enqueue(conn)?;
92+
}
8893

8994
ok_true()
9095
}

src/models/dependency.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,16 @@ pub enum DependencyKind {
4444
// if you add a kind here, be sure to update `from_row` below.
4545
}
4646

47+
impl From<IndexDependencyKind> for DependencyKind {
48+
fn from(dk: IndexDependencyKind) -> Self {
49+
match dk {
50+
IndexDependencyKind::Normal => DependencyKind::Normal,
51+
IndexDependencyKind::Build => DependencyKind::Build,
52+
IndexDependencyKind::Dev => DependencyKind::Dev,
53+
}
54+
}
55+
}
56+
4757
impl From<DependencyKind> for IndexDependencyKind {
4858
fn from(dk: DependencyKind) -> Self {
4959
match dk {

0 commit comments

Comments
 (0)