refactor: ensure in-memory database consistency

test: update authifier to allow for in-memory tests
ci: explicitly run in-memory and mongo tests
This commit is contained in:
Paul Makles
2023-09-10 14:49:27 +01:00
parent 055deab105
commit 6838b0b1f0
12 changed files with 92 additions and 58 deletions

View File

@@ -30,23 +30,26 @@ jobs:
run: | run: |
docker-compose -f docker-compose.db.yml up -d docker-compose -f docker-compose.db.yml up -d
- name: Copy .env.example
if: github.event_name != 'pull_request' && github.ref_name == 'master'
run: |
cp .env.example .env
- name: Run cargo test - name: Run cargo test
uses: actions-rs/cargo@v1 uses: actions-rs/cargo@v1
env:
TEST_DB: REFERENCE
with: with:
command: test command: test
- name: Run cargo test (with MongoDB) - name: Run cargo test (with MongoDB)
uses: actions-rs/cargo@v1 uses: actions-rs/cargo@v1
env: env:
TEST_DB: MONGODB
MONGODB: mongodb://localhost MONGODB: mongodb://localhost
with: with:
command: test command: test
- name: Copy .env.example
if: github.event_name != 'pull_request' && github.ref_name == 'master'
run: |
cp .env.example .env
- name: Start API in background - name: Start API in background
if: github.event_name != 'pull_request' && github.ref_name == 'master' if: github.event_name != 'pull_request' && github.ref_name == 'master'
run: | run: |

9
Cargo.lock generated
View File

@@ -347,9 +347,9 @@ dependencies = [
[[package]] [[package]]
name = "authifier" name = "authifier"
version = "1.0.7" version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a84411393a4326726ead660991ce8047f1865fa89900fb6c18e1e6c513cf1f9b" checksum = "30269caf0aaf1e1b542b150030e9688bf41d50026e09a51efd9408f332636c9d"
dependencies = [ dependencies = [
"async-std", "async-std",
"async-trait", "async-trait",
@@ -3573,6 +3573,7 @@ version = "0.6.8"
dependencies = [ dependencies = [
"async-channel", "async-channel",
"async-std", "async-std",
"authifier",
"bitfield", "bitfield",
"chrono", "chrono",
"dashmap", "dashmap",
@@ -3859,9 +3860,9 @@ dependencies = [
[[package]] [[package]]
name = "rocket_authifier" name = "rocket_authifier"
version = "1.0.7" version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4554a81937341d8c3cd3e43431ac2d23624444dc3a88e7ffd3ff66593779293" checksum = "5f89a12311f60e9288833fc3ce6029bce5d5c61870ceef74d4a50668a8b520ad"
dependencies = [ dependencies = [
"authifier", "authifier",
"iso8601-timestamp 0.1.10", "iso8601-timestamp 0.1.10",

View File

@@ -5,3 +5,5 @@ members = ["crates/delta", "crates/bonfire", "crates/quark", "crates/core/*"]
# mobc-redis = { git = "https://github.com/insertish/mobc", rev = "8b880bb59f2ba80b4c7bc40c649c113d8857a186" } # mobc-redis = { git = "https://github.com/insertish/mobc", rev = "8b880bb59f2ba80b4c7bc40c649c113d8857a186" }
redis22 = { package = "redis", version = "0.22.3", git = "https://github.com/revoltchat/redis-rs", rev = "1a41faf356fd21aebba71cea7eb7eb2653e5f0ef" } redis22 = { package = "redis", version = "0.22.3", git = "https://github.com/revoltchat/redis-rs", rev = "1a41faf356fd21aebba71cea7eb7eb2653e5f0ef" }
redis23 = { package = "redis", version = "0.23.1", git = "https://github.com/revoltchat/redis-rs", rev = "f8ca28ab85da59d2ccde526b4d2fb390eff5a5f9" } redis23 = { package = "redis", version = "0.23.1", git = "https://github.com/revoltchat/redis-rs", rev = "f8ca28ab85da59d2ccde526b4d2fb390eff5a5f9" }
# authifier = { package = "authifier", version = "1.0.8", path = "../authifier/crates/authifier" }
# rocket_authifier = { package = "rocket_authifier", version = "1.0.8", path = "../authifier/crates/rocket_authifier" }

View File

@@ -86,4 +86,4 @@ fcm = "0.9.2"
web-push = "0.10.0" web-push = "0.10.0"
# Authifier # Authifier
authifier = { version = "1.0" } authifier = { version = "1.0.8" }

View File

@@ -1,6 +1,8 @@
mod mongodb; mod mongodb;
mod reference; mod reference;
use revolt_config::config;
pub use self::mongodb::*; pub use self::mongodb::*;
pub use self::reference::*; pub use self::reference::*;
@@ -31,25 +33,41 @@ impl DatabaseInfo {
/// Create a database client from the given database information /// Create a database client from the given database information
#[async_recursion] #[async_recursion]
pub async fn connect(self) -> Result<Database, String> { pub async fn connect(self) -> Result<Database, String> {
let config = config().await;
Ok(match self { Ok(match self {
DatabaseInfo::Auto => { DatabaseInfo::Auto => {
if let Ok(uri) = std::env::var("MONGODB") { if std::env::var("TEST_DB").is_ok() {
return DatabaseInfo::MongoDb { DatabaseInfo::Test("revolt_test".to_string())
uri, .connect()
.await?
} else if !config.database.mongodb.is_empty() {
DatabaseInfo::MongoDb {
uri: config.database.mongodb,
database_name: "revolt".to_string(), database_name: "revolt".to_string(),
} }
.connect() .connect()
.await; .await?
} else {
DatabaseInfo::Reference.connect().await?
} }
DatabaseInfo::Reference.connect().await?
} }
DatabaseInfo::Test(database_name) => { DatabaseInfo::Test(database_name) => {
if let Ok(uri) = std::env::var("MONGODB") { match std::env::var("TEST_DB")
return DatabaseInfo::MongoDb { uri, database_name }.connect().await; .expect("`TEST_DB` environment variable should be set to REFERENCE or MONGODB")
.as_str()
{
"REFERENCE" => DatabaseInfo::Reference.connect().await?,
"MONGODB" => {
DatabaseInfo::MongoDb {
uri: config.database.mongodb,
database_name,
}
.connect()
.await?
}
_ => unreachable!("must specify REFERENCE or MONGODB"),
} }
DatabaseInfo::Reference.connect().await?
} }
DatabaseInfo::Reference => Database::Reference(Default::default()), DatabaseInfo::Reference => Database::Reference(Default::default()),
DatabaseInfo::MongoDb { uri, database_name } => { DatabaseInfo::MongoDb { uri, database_name } => {
@@ -65,14 +83,3 @@ impl DatabaseInfo {
}) })
} }
} }
impl From<Database> for authifier::Database {
fn from(value: Database) -> Self {
match value {
Database::Reference(_) => Default::default(),
Database::MongoDb(MongoDb(client, _)) => authifier::Database::MongoDb(
authifier::database::MongoDb(client.database("revolt")),
),
}
}
}

View File

@@ -13,12 +13,12 @@ pub mod process_embeds;
pub mod web_push; pub mod web_push;
/// Spawn background workers /// Spawn background workers
pub async fn start_workers(db: Database) { pub async fn start_workers(db: Database, authifier_db: authifier::Database) {
for _ in 0..WORKER_COUNT { for _ in 0..WORKER_COUNT {
task::spawn(ack::worker(db.clone())); task::spawn(ack::worker(db.clone()));
task::spawn(last_message_id::worker(db.clone())); task::spawn(last_message_id::worker(db.clone()));
task::spawn(process_embeds::worker(db.clone())); task::spawn(process_embeds::worker(db.clone()));
task::spawn(web_push::worker(db.clone().into())); task::spawn(web_push::worker(authifier_db.clone()));
} }
} }

View File

@@ -57,7 +57,7 @@ rocket = { version = "0.5.0-rc.2", default-features = false, features = [
] } ] }
rocket_cors = { git = "https://github.com/lawliet89/rocket_cors", rev = "c17e8145baa4790319fdb6a473e465b960f55e7c" } rocket_cors = { git = "https://github.com/lawliet89/rocket_cors", rev = "c17e8145baa4790319fdb6a473e465b960f55e7c" }
rocket_empty = { version = "0.1.1", features = ["schema"] } rocket_empty = { version = "0.1.1", features = ["schema"] }
rocket_authifier = { version = "1.0.7" } rocket_authifier = { version = "1.0.8" }
rocket_prometheus = "0.10.0-rc.3" rocket_prometheus = "0.10.0-rc.3"
# spec generation # spec generation
@@ -68,6 +68,7 @@ revolt_rocket_okapi = { version = "0.9.1", features = ["swagger"] }
revolt-quark = { path = "../quark" } revolt-quark = { path = "../quark" }
# core # core
authifier = "1.0.8"
revolt-config = { path = "../core/config" } revolt-config = { path = "../core/config" }
revolt-database = { path = "../core/database", features = [ revolt-database = { path = "../core/database", features = [
"rocket-impl", "rocket-impl",

View File

@@ -8,6 +8,7 @@ extern crate serde_json;
pub mod routes; pub mod routes;
pub mod util; pub mod util;
use revolt_database::{Database, MongoDb};
use rocket::{Build, Rocket}; use rocket::{Build, Rocket};
use rocket_cors::{AllowedOrigins, CorsOptions}; use rocket_cors::{AllowedOrigins, CorsOptions};
use rocket_prometheus::PrometheusMetrics; use rocket_prometheus::PrometheusMetrics;
@@ -33,7 +34,12 @@ pub async fn web() -> Rocket<Build> {
// Setup Authifier // Setup Authifier
let authifier = Authifier { let authifier = Authifier {
database: db.clone().into(), database: match db.clone() {
Database::Reference(_) => Default::default(),
Database::MongoDb(MongoDb(client, _)) => authifier::Database::MongoDb(
authifier::database::MongoDb(client.database("revolt")),
),
},
config: revolt_quark::util::authifier::config(), config: revolt_quark::util::authifier::config(),
event_channel: Some(sender), event_channel: Some(sender),
}; };
@@ -55,8 +61,14 @@ pub async fn web() -> Rocket<Build> {
}); });
// Launch background task workers // Launch background task workers
async_std::task::spawn(revolt_database::tasks::start_workers(db.clone())); async_std::task::spawn(revolt_database::tasks::start_workers(
async_std::task::spawn(revolt_quark::tasks::start_workers(legacy_db.clone())); db.clone(),
authifier.database.clone(),
));
async_std::task::spawn(revolt_quark::tasks::start_workers(
legacy_db.clone(),
authifier.database.clone(),
));
// Configure CORS // Configure CORS
let cors = CorsOptions { let cors = CorsOptions {

View File

@@ -1,7 +1,7 @@
use futures::StreamExt; use futures::StreamExt;
use rand::Rng; use rand::Rng;
use redis_kiss::redis::aio::PubSub; use redis_kiss::redis::aio::PubSub;
use revolt_database::{events::client::EventV1, Database, DatabaseInfo, User}; use revolt_database::{events::client::EventV1, Database, User};
use revolt_quark::authifier::{ use revolt_quark::authifier::{
models::{Account, Session}, models::{Account, Session},
Authifier, Authifier,
@@ -24,20 +24,27 @@ impl TestHarness {
.await .await
.expect("valid rocket instance"); .expect("valid rocket instance");
let db = DatabaseInfo::Auto.connect().await.expect("`Database`");
let mut sub = redis_kiss::open_pubsub_connection() let mut sub = redis_kiss::open_pubsub_connection()
.await .await
.expect("`PubSub`"); .expect("`PubSub`");
sub.psubscribe("*").await.unwrap(); sub.psubscribe("*").await.unwrap();
let db = client
.rocket()
.state::<Database>()
.expect("`Database`")
.clone();
let authifier = client
.rocket()
.state::<Authifier>()
.expect("`Authifier`")
.clone();
TestHarness { TestHarness {
client, client,
authifier: Authifier { authifier,
database: db.clone().into(),
config: revolt_quark::util::authifier::config(),
event_channel: None,
},
db, db,
sub, sub,
event_buffer: vec![], event_buffer: vec![],

View File

@@ -88,7 +88,7 @@ rocket_empty = { version = "0.1.1", optional = true, features = ["schema"] }
rocket_cors = { optional = true, git = "https://github.com/lawliet89/rocket_cors", rev = "c17e8145baa4790319fdb6a473e465b960f55e7c" } rocket_cors = { optional = true, git = "https://github.com/lawliet89/rocket_cors", rev = "c17e8145baa4790319fdb6a473e465b960f55e7c" }
# Authifier # Authifier
authifier = { version = "1.0.7", features = ["async-std-runtime"] } authifier = { version = "1.0.8", features = ["async-std-runtime"] }
# Sentry # Sentry
sentry = "0.31.5" sentry = "0.31.5"

View File

@@ -31,6 +31,18 @@ impl DatabaseInfo {
pub async fn connect(self) -> Result<Database, String> { pub async fn connect(self) -> Result<Database, String> {
Ok(match self { Ok(match self {
DatabaseInfo::Auto => { DatabaseInfo::Auto => {
if let Ok(test_db) = env::var("TEST_DB") {
return match test_db.as_str() {
"REFERENCE" => DatabaseInfo::Dummy.connect().await,
"MONGODB" => {
DatabaseInfo::MongoDb(env::var("MONGODB").expect("`MONGODB` env"))
.connect()
.await
}
_ => unreachable!("must specify REFERENCE or MONGODB"),
};
}
if let Ok(uri) = env::var("MONGODB") { if let Ok(uri) = env::var("MONGODB") {
return DatabaseInfo::MongoDb(uri).connect().await; return DatabaseInfo::MongoDb(uri).connect().await;
} }
@@ -61,17 +73,6 @@ impl Deref for Database {
} }
} }
impl From<Database> for authifier::Database {
fn from(val: Database) -> Self {
match val {
Database::Dummy(_) => authifier::Database::default(),
Database::MongoDb(MongoDb(client)) => authifier::Database::MongoDb(
authifier::database::MongoDb(client.database("revolt")),
),
}
}
}
impl From<Database> for revolt_database::Database { impl From<Database> for revolt_database::Database {
fn from(val: Database) -> Self { fn from(val: Database) -> Self {
match val { match val {

View File

@@ -13,12 +13,12 @@ pub mod process_embeds;
pub mod web_push; pub mod web_push;
/// Spawn background workers /// Spawn background workers
pub async fn start_workers(db: Database) { pub async fn start_workers(db: Database, authifier_db: authifier::Database) {
for _ in 0..WORKER_COUNT { for _ in 0..WORKER_COUNT {
task::spawn(ack::worker(db.clone())); task::spawn(ack::worker(db.clone()));
task::spawn(last_message_id::worker(db.clone())); task::spawn(last_message_id::worker(db.clone()));
task::spawn(process_embeds::worker(db.clone())); task::spawn(process_embeds::worker(db.clone()));
task::spawn(web_push::worker(db.clone().into())); task::spawn(web_push::worker(authifier_db.clone()));
} }
} }