Skip to content

Commit a9cfc37

Browse files
Some small Labrinth refactors and fixes (#3698)
* chore(labrinth): fix typos, simplify out `remove_duplicates` func * fix(labrinth): implement `capitalize_first` so that it can't panic on wide chars * chore(labrinth): refactor out unneeded clone highlighted by nightly Clippy lints * chore(labrinth): simplify `capitalize_first` implementation * fix(labrinth): preserve ordering when deduplicating project field values This addresses an unintended behavior change on 157647f. * fix(labrinth/tests): make `index_swaps` test run successfully I wonder why we don't run these more often... * refactor: rename `.env.example` files to `.env.local`, make local envs more consistent between frontend and backend * chore(labrinth/.env.local): proper email verif. and password reset paths
1 parent be37f07 commit a9cfc37

File tree

10 files changed

+36
-48
lines changed

10 files changed

+36
-48
lines changed
File renamed without changes.

apps/docs/src/content/docs/contributing/labrinth.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ This project is part of our [monorepo](https://github.com/modrinth/code). You ca
77

88
[labrinth] is the Rust-based backend serving Modrinth's API with the help of the [Actix](https://actix.rs) framework. To get started with a labrinth instance, install docker, docker-compose (which comes with Docker), and [Rust]. The initial startup can be done simply with the command `docker-compose up`, or with `docker compose up` (Compose V2 and later). That will deploy a PostgreSQL database on port 5432 and a MeiliSearch instance on port 7700. To run the API itself, you'll need to use the `cargo run` command, this will deploy the API on port 8000.
99

10-
To get a basic configuration, copy the `.env.example` file to `.env`. Now, you'll have to install the sqlx CLI, which can be done with cargo:
10+
To get a basic configuration, copy the `.env.local` file to `.env`. Now, you'll have to install the sqlx CLI, which can be done with cargo:
1111

1212
```bash
1313
cargo install --git https://github.com/launchbadge/sqlx sqlx-cli --no-default-features --features postgres,rustls

apps/frontend/.env.example

Lines changed: 0 additions & 3 deletions
This file was deleted.

apps/frontend/.env.local

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
BASE_URL=http://127.0.0.1:8000/v2/
2+
BROWSER_BASE_URL=http://127.0.0.1:8000/v2/
3+
PYRO_BASE_URL=https://staging-archon.modrinth.com
4+
PROD_OVERRIDE=true
5+

apps/labrinth/.env.example renamed to apps/labrinth/.env.local

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ DEBUG=true
22
RUST_LOG=info,sqlx::query=warn
33
SENTRY_DSN=none
44

5-
SITE_URL=https://modrinth.com
5+
SITE_URL=http://localhost:3000
66
CDN_URL=https://staging-cdn.modrinth.com
77
LABRINTH_ADMIN_KEY=feedbeef
88
RATE_LIMIT_IGNORE_KEY=feedbeef
@@ -87,8 +87,8 @@ SMTP_HOST=none
8787
SMTP_PORT=465
8888
SMTP_TLS=tls
8989

90-
SITE_VERIFY_EMAIL_PATH=none
91-
SITE_RESET_PASSWORD_PATH=none
90+
SITE_VERIFY_EMAIL_PATH=auth/verify-email
91+
SITE_RESET_PASSWORD_PATH=auth/reset-password
9292
SITE_BILLING_PATH=none
9393

9494
SENDY_URL=none

apps/labrinth/src/models/v3/projects.rs

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
use std::collections::{HashMap, HashSet};
1+
use std::collections::HashMap;
2+
use std::mem;
23

34
use crate::database::models::loader_fields::VersionField;
45
use crate::database::models::project_item::{LinkUrl, ProjectQueryResult};
@@ -8,6 +9,7 @@ use crate::models::ids::{
89
};
910
use ariadne::ids::UserId;
1011
use chrono::{DateTime, Utc};
12+
use itertools::Itertools;
1113
use serde::{Deserialize, Serialize};
1214
use validator::Validate;
1315

@@ -95,19 +97,6 @@ pub struct Project {
9597
pub fields: HashMap<String, Vec<serde_json::Value>>,
9698
}
9799

98-
fn remove_duplicates(values: Vec<serde_json::Value>) -> Vec<serde_json::Value> {
99-
let mut seen = HashSet::new();
100-
values
101-
.into_iter()
102-
.filter(|value| {
103-
// Convert the JSON value to a string for comparison
104-
let as_string = value.to_string();
105-
// Check if the string is already in the set
106-
seen.insert(as_string)
107-
})
108-
.collect()
109-
}
110-
111100
// This is a helper function to convert a list of VersionFields into a HashMap of field name to vecs of values
112101
// This allows for removal of duplicates
113102
pub fn from_duplicate_version_fields(
@@ -132,9 +121,9 @@ pub fn from_duplicate_version_fields(
132121
}
133122
}
134123

135-
// Remove duplicates by converting to string and back
124+
// Remove duplicates
136125
for (_, v) in fields.iter_mut() {
137-
*v = remove_duplicates(v.clone());
126+
*v = mem::take(v).into_iter().unique().collect_vec();
138127
}
139128
fields
140129
}
@@ -624,7 +613,7 @@ pub struct Version {
624613
pub downloads: u32,
625614
/// The type of the release - `Alpha`, `Beta`, or `Release`.
626615
pub version_type: VersionType,
627-
/// The status of tne version
616+
/// The status of the version
628617
pub status: VersionStatus,
629618
/// The requested status of the version (used for scheduling)
630619
pub requested_status: Option<VersionStatus>,
@@ -880,7 +869,7 @@ impl std::fmt::Display for DependencyType {
880869
}
881870

882871
impl DependencyType {
883-
// These are constant, so this can remove unneccessary allocations (`to_string`)
872+
// These are constant, so this can remove unnecessary allocations (`to_string`)
884873
pub fn as_str(&self) -> &'static str {
885874
match self {
886875
DependencyType::Required => "required",

apps/labrinth/src/routes/v2_reroute.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -264,11 +264,11 @@ pub fn convert_side_types_v2_bools(
264264
}
265265

266266
pub fn capitalize_first(input: &str) -> String {
267-
let mut result = input.to_owned();
268-
if let Some(first_char) = result.get_mut(0..1) {
269-
first_char.make_ascii_uppercase();
270-
}
271-
result
267+
input
268+
.chars()
269+
.enumerate()
270+
.map(|(i, c)| if i == 0 { c.to_ascii_uppercase() } else { c })
271+
.collect()
272272
}
273273

274274
#[cfg(test)]

apps/labrinth/src/routes/v3/version_file.rs

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,9 @@ pub async fn get_version_from_hash(
5252
.map(|x| x.1)
5353
.ok();
5454
let hash = info.into_inner().0.to_lowercase();
55-
let algorithm = hash_query
56-
.algorithm
57-
.clone()
58-
.unwrap_or_else(|| default_algorithm_from_hashes(&[hash.clone()]));
55+
let algorithm = hash_query.algorithm.clone().unwrap_or_else(|| {
56+
default_algorithm_from_hashes(std::slice::from_ref(&hash))
57+
});
5958
let file = database::models::DBVersion::get_file_from_hash(
6059
algorithm,
6160
hash,
@@ -140,10 +139,9 @@ pub async fn get_update_from_hash(
140139
.ok();
141140
let hash = info.into_inner().0.to_lowercase();
142141
if let Some(file) = database::models::DBVersion::get_file_from_hash(
143-
hash_query
144-
.algorithm
145-
.clone()
146-
.unwrap_or_else(|| default_algorithm_from_hashes(&[hash.clone()])),
142+
hash_query.algorithm.clone().unwrap_or_else(|| {
143+
default_algorithm_from_hashes(std::slice::from_ref(&hash))
144+
}),
147145
hash,
148146
hash_query.version_id.map(|x| x.into()),
149147
&**pool,
@@ -577,10 +575,9 @@ pub async fn delete_file(
577575
.1;
578576

579577
let hash = info.into_inner().0.to_lowercase();
580-
let algorithm = hash_query
581-
.algorithm
582-
.clone()
583-
.unwrap_or_else(|| default_algorithm_from_hashes(&[hash.clone()]));
578+
let algorithm = hash_query.algorithm.clone().unwrap_or_else(|| {
579+
default_algorithm_from_hashes(std::slice::from_ref(&hash))
580+
});
584581
let file = database::models::DBVersion::get_file_from_hash(
585582
algorithm.clone(),
586583
hash,
@@ -709,10 +706,9 @@ pub async fn download_version(
709706
.ok();
710707

711708
let hash = info.into_inner().0.to_lowercase();
712-
let algorithm = hash_query
713-
.algorithm
714-
.clone()
715-
.unwrap_or_else(|| default_algorithm_from_hashes(&[hash.clone()]));
709+
let algorithm = hash_query.algorithm.clone().unwrap_or_else(|| {
710+
default_algorithm_from_hashes(std::slice::from_ref(&hash))
711+
});
716712
let file = database::models::DBVersion::get_file_from_hash(
717713
algorithm.clone(),
718714
hash,

apps/labrinth/tests/search.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ async fn index_swaps() {
151151
test_env.api.remove_project("alpha", USER_USER_PAT).await;
152152
assert_status!(&resp, StatusCode::NO_CONTENT);
153153

154-
// We should not get any results, because the project has been deleted
154+
// Deletions should not be indexed immediately
155155
let projects = test_env
156156
.api
157157
.search_deserialized(
@@ -160,7 +160,8 @@ async fn index_swaps() {
160160
USER_USER_PAT,
161161
)
162162
.await;
163-
assert_eq!(projects.total_hits, 0);
163+
assert_eq!(projects.total_hits, 1);
164+
assert!(projects.hits[0].slug.as_ref().unwrap().contains("alpha"));
164165

165166
// But when we reindex, it should be gone
166167
let resp = test_env.api.reset_search_index().await;
File renamed without changes.

0 commit comments

Comments
 (0)