Skip to content

Commit 9d36a16

Browse files
committed
Merge branch 'release/v0.13.5'
2 parents 2e49621 + ca01090 commit 9d36a16

File tree

18 files changed

+143
-52
lines changed

18 files changed

+143
-52
lines changed

CHANGELOG.md

+7
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
66

77
## [Unreleased]
88

9+
## [[0.13.5]](https://github.com/thoth-pub/thoth/releases/tag/v0.13.5) - 2025-01-17
10+
### Changed
11+
- [665](https://github.com/thoth-pub/thoth/pull/665) - Removed unnecessary `map_or()` to comply with [`rustc 1.84.0`](https://github.com/rust-lang/rust/releases/tag/1.84.0)
12+
- [666](https://github.com/thoth-pub/thoth/pull/666) - Upgrade rust to `1.84.0` in production `Dockerfile`
13+
14+
### Added
15+
- [666](https://github.com/thoth-pub/thoth/pull/666) - CLI subcommand `thoth cache delete` to delete cached metadata records by specification ID
916

1017
## [[0.13.4]](https://github.com/thoth-pub/thoth/releases/tag/v0.13.4) - 2024-12-11
1118
### Added

Cargo.lock

+15-14
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+7-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "thoth"
3-
version = "0.13.4"
3+
version = "0.13.5"
44
authors = ["Javier Arias <javi@thoth.pub>", "Ross Higman <ross@thoth.pub>"]
55
edition = "2021"
66
license = "Apache-2.0"
@@ -15,11 +15,12 @@ maintenance = { status = "actively-developed" }
1515
members = ["thoth-api", "thoth-api-server", "thoth-app", "thoth-app-server", "thoth-client", "thoth-errors", "thoth-export-server"]
1616

1717
[dependencies]
18-
thoth-api = { version = "=0.13.4", path = "thoth-api", features = ["backend"] }
19-
thoth-api-server = { version = "=0.13.4", path = "thoth-api-server" }
20-
thoth-app-server = { version = "=0.13.4", path = "thoth-app-server" }
21-
thoth-errors = { version = "=0.13.4", path = "thoth-errors" }
22-
thoth-export-server = { version = "=0.13.4", path = "thoth-export-server" }
18+
thoth-api = { version = "=0.13.5", path = "thoth-api", features = ["backend"] }
19+
thoth-api-server = { version = "=0.13.5", path = "thoth-api-server" }
20+
thoth-app-server = { version = "=0.13.5", path = "thoth-app-server" }
21+
thoth-errors = { version = "=0.13.5", path = "thoth-errors" }
22+
thoth-export-server = { version = "=0.13.5", path = "thoth-export-server" }
2323
clap = { version = "4.5.21", features = ["cargo", "env"] }
2424
dialoguer = { version = "0.11.0", features = ["password"] }
2525
dotenv = "0.15.0"
26+
tokio = { version = "1.43.0", features = ["rt", "rt-multi-thread", "macros"] }

Dockerfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
ARG MUSL_IMAGE=clux/muslrust:1.83.0-stable
1+
ARG MUSL_IMAGE=clux/muslrust:1.84.0-stable
22

33
FROM ${MUSL_IMAGE} as build
44

src/bin/thoth.rs

+49-9
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,19 @@ use clap::{crate_authors, crate_version, value_parser, Arg, ArgAction, Command};
22
use dialoguer::{console::Term, theme::ColorfulTheme, Input, MultiSelect, Password, Select};
33
use dotenv::dotenv;
44
use std::env;
5-
use thoth::api::account::model::{AccountData, LinkedPublisher};
6-
use thoth::api::account::service::{all_emails, all_publishers, register, update_password};
7-
use thoth::api::db::{init_pool, revert_migrations, run_migrations};
8-
use thoth::api_server;
9-
use thoth::app_server;
10-
use thoth::export_server;
11-
use thoth_errors::ThothResult;
5+
use thoth::{
6+
api::{
7+
account::{
8+
model::{AccountData, LinkedPublisher},
9+
service::{all_emails, all_publishers, register, update_password},
10+
},
11+
db::{init_pool as init_pg_pool, revert_migrations, run_migrations},
12+
redis::{del, init_pool as init_redis_pool, scan_match},
13+
},
14+
api_server, app_server,
15+
errors::{ThothError, ThothResult},
16+
export_server, ALL_SPECIFICATIONS,
17+
};
1218

1319
fn database_argument() -> Arg {
1420
Arg::new("db")
@@ -220,6 +226,14 @@ fn thoth_commands() -> Command {
220226
.subcommand(Command::new("register").about("Create a new user account"))
221227
.subcommand(Command::new("password").about("Reset a password")),
222228
)
229+
.subcommand(
230+
Command::new("cache")
231+
.about("Manage cached records")
232+
.arg(redis_argument())
233+
.subcommand_required(true)
234+
.arg_required_else_help(true)
235+
.subcommand(Command::new("delete").about("Delete cached records")),
236+
)
223237
}
224238

225239
fn main() -> ThothResult<()> {
@@ -326,7 +340,7 @@ fn main() -> ThothResult<()> {
326340
let database_url = account_matches.get_one::<String>("db").unwrap();
327341
match account_matches.subcommand() {
328342
Some(("register", _)) => {
329-
let pool = init_pool(database_url);
343+
let pool = init_pg_pool(database_url);
330344

331345
let name = Input::new()
332346
.with_prompt("Enter given name")
@@ -383,7 +397,7 @@ fn main() -> ThothResult<()> {
383397
register(account_data, linked_publishers, &pool).map(|_| ())
384398
}
385399
Some(("password", _)) => {
386-
let pool = init_pool(database_url);
400+
let pool = init_pg_pool(database_url);
387401
let all_emails =
388402
all_emails(&pool).expect("No user accounts present in database.");
389403
let email_selection = Select::with_theme(&ColorfulTheme::default())
@@ -402,6 +416,32 @@ fn main() -> ThothResult<()> {
402416
_ => unreachable!(),
403417
}
404418
}
419+
Some(("cache", cache_matches)) => match cache_matches.subcommand() {
420+
Some(("delete", _)) => {
421+
let redis_url = cache_matches.get_one::<String>("redis").unwrap();
422+
let pool = init_redis_pool(redis_url);
423+
let chosen: Vec<usize> = MultiSelect::new()
424+
.items(&ALL_SPECIFICATIONS)
425+
.with_prompt("Select cached specifications to delete")
426+
.interact_on(&Term::stdout())?;
427+
// run a separate tokio runtime to avoid interfering with actix's threads
428+
let runtime = tokio::runtime::Builder::new_multi_thread()
429+
.worker_threads(1)
430+
.enable_all()
431+
.build()?;
432+
runtime.block_on(async {
433+
for index in chosen {
434+
let specification = ALL_SPECIFICATIONS.get(index).unwrap();
435+
let keys = scan_match(&pool, &format!("{}*", specification)).await?;
436+
for key in keys {
437+
del(&pool, &key).await?;
438+
}
439+
}
440+
Ok::<(), ThothError>(())
441+
})
442+
}
443+
_ => unreachable!(),
444+
},
405445
_ => unreachable!(),
406446
}
407447
}

src/lib.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
pub use thoth_api as api;
22
pub use thoth_api_server::start_server as api_server;
33
pub use thoth_app_server::start_server as app_server;
4-
pub use thoth_export_server::start_server as export_server;
4+
pub use thoth_errors as errors;
5+
pub use thoth_export_server::{start_server as export_server, ALL_SPECIFICATIONS};

thoth-api-server/Cargo.toml

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "thoth-api-server"
3-
version = "0.13.4"
3+
version = "0.13.5"
44
authors = ["Javier Arias <javi@thoth.pub>", "Ross Higman <ross@thoth.pub>"]
55
edition = "2021"
66
license = "Apache-2.0"
@@ -9,8 +9,8 @@ repository = "https://github.com/thoth-pub/thoth"
99
readme = "README.md"
1010

1111
[dependencies]
12-
thoth-api = { version = "=0.13.4", path = "../thoth-api", features = ["backend"] }
13-
thoth-errors = { version = "=0.13.4", path = "../thoth-errors" }
12+
thoth-api = { version = "=0.13.5", path = "../thoth-api", features = ["backend"] }
13+
thoth-errors = { version = "=0.13.5", path = "../thoth-errors" }
1414
actix-web = "4.9"
1515
actix-cors = "0.7.0"
1616
actix-http = "3.9.0"

thoth-api/Cargo.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "thoth-api"
3-
version = "0.13.4"
3+
version = "0.13.5"
44
authors = ["Javier Arias <javi@thoth.pub>", "Ross Higman <ross@thoth.pub>"]
55
edition = "2021"
66
license = "Apache-2.0"
@@ -15,7 +15,7 @@ maintenance = { status = "actively-developed" }
1515
backend = ["diesel", "diesel-derive-enum", "diesel_migrations", "futures", "actix-web", "jsonwebtoken", "deadpool-redis"]
1616

1717
[dependencies]
18-
thoth-errors = { version = "=0.13.4", path = "../thoth-errors" }
18+
thoth-errors = { version = "=0.13.5", path = "../thoth-errors" }
1919
actix-web = { version = "4.9", optional = true }
2020
argon2rs = "0.2.5"
2121
isbn2 = "0.4.0"

thoth-api/src/graphql/model.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1985,7 +1985,7 @@ impl MutationRoot {
19851985
Some(vec![LocationPlatform::Thoth]),
19861986
)?
19871987
.first()
1988-
.map_or(false, |location| location.canonical);
1988+
.is_some_and(|location| location.canonical);
19891989
// Only superusers can update the canonical location when a Thoth Location Platform canonical location already exists
19901990
if has_canonical_thoth_location && data.canonical && !context.account_access.is_superuser {
19911991
return Err(ThothError::ThothUpdateCanonicalError.into());

thoth-api/src/redis.rs

+34
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use deadpool_redis::{redis::AsyncCommands, Config, Connection, Pool};
2+
use futures::StreamExt;
23
use thoth_errors::ThothResult;
34

45
pub type RedisPool = Pool;
@@ -31,6 +32,12 @@ pub async fn del(pool: &RedisPool, key: &str) -> ThothResult<String> {
3132
con.del(key).await.map_err(Into::into)
3233
}
3334

35+
pub async fn scan_match(pool: &RedisPool, pattern: &str) -> ThothResult<Vec<String>> {
36+
let mut con = create_connection(pool).await?;
37+
let keys: Vec<String> = con.scan_match(pattern).await?.collect().await;
38+
Ok(keys)
39+
}
40+
3441
#[cfg(test)]
3542
mod tests {
3643
use super::*;
@@ -73,4 +80,31 @@ mod tests {
7380
let get_result = get(&pool, test_key).await;
7481
assert!(get_result.is_err());
7582
}
83+
84+
#[tokio::test]
85+
async fn test_del() {
86+
let pool = get_pool().await;
87+
let test_key = "test_key_to_delete";
88+
let test_value = "test_value";
89+
set(&pool, test_key, test_value).await.unwrap();
90+
91+
let del_result = del(&pool, test_key).await;
92+
assert!(del_result.is_ok());
93+
let get_result = get(&pool, test_key).await;
94+
assert!(get_result.is_err());
95+
}
96+
97+
#[tokio::test]
98+
async fn test_scan_match() {
99+
let pool = get_pool().await;
100+
set(&pool, "onix_3.0::key1", "value1").await.unwrap();
101+
set(&pool, "onix_3.0::key2", "value2").await.unwrap();
102+
set(&pool, "onix_3.0::key3", "value3").await.unwrap();
103+
104+
let keys = scan_match(&pool, "onix_3.0::*").await.unwrap();
105+
assert_eq!(keys.len(), 3);
106+
assert!(keys.contains(&"onix_3.0::key1".to_string()));
107+
assert!(keys.contains(&"onix_3.0::key2".to_string()));
108+
assert!(keys.contains(&"onix_3.0::key3".to_string()));
109+
}
76110
}

thoth-app-server/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "thoth-app-server"
3-
version = "0.13.4"
3+
version = "0.13.5"
44
authors = ["Javier Arias <javi@thoth.pub>", "Ross Higman <ross@thoth.pub>"]
55
edition = "2021"
66
license = "Apache-2.0"

thoth-app/Cargo.toml

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "thoth-app"
3-
version = "0.13.4"
3+
version = "0.13.5"
44
authors = ["Javier Arias <javi@thoth.pub>", "Ross Higman <ross@thoth.pub>"]
55
edition = "2021"
66
license = "Apache-2.0"
@@ -29,8 +29,8 @@ semver = "1.0.23"
2929
serde = { version = "1.0", features = ["derive"] }
3030
serde_json = "1.0"
3131
uuid = { version = "1.11.0", features = ["serde", "v4", "js"] }
32-
thoth-api = { version = "=0.13.4", path = "../thoth-api" }
33-
thoth-errors = { version = "=0.13.4", path = "../thoth-errors" }
32+
thoth-api = { version = "=0.13.5", path = "../thoth-api" }
33+
thoth-errors = { version = "=0.13.5", path = "../thoth-errors" }
3434

3535
[build-dependencies]
3636
dotenv = "0.15.0"

0 commit comments

Comments
 (0)