Skip to content

Commit

Permalink
refactor how loading the mock data is done
Browse files Browse the repository at this point in the history
  • Loading branch information
amirRamirfatahi committed Jan 23, 2025
1 parent 4060940 commit f0a81f3
Show file tree
Hide file tree
Showing 16 changed files with 186 additions and 160 deletions.
5 changes: 4 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,12 @@ jobs:
# - name: Install dependencies
# run: cargo build --release

- name: Load Mock Data
run: cargo run --bin mockdb

- name: Run integration tests
run: SYNC_DB=true cargo test
run: cargo test

- name: Tear down Docker Compose
if: always()
Expand Down
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ path = "src/service.rs"
name = "watcher"
path = "src/watcher.rs"

[[bin]]
name = "mockdb"
path = "src/mock_db.rs"

[[bench]]
name = "user"
harness = false
Expand Down
33 changes: 12 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,18 +90,22 @@ To contribute to Nexus, follow these steps:

### Running Tests

To run all tests:
Running tests requires setting up mock data into Neo4j and Redis.

Use the `mockdb` binary to load the mock data.
```bash
cargo test
cargo run --bin mockdb [database]
```

You can optionally pass the `SYNC_DB` env var to control setting up the testing data in mocks folder.
You can pass:
`database` is optional and can be either `graph` or `redis`. Not providing any value will sync all the databases.

You can optionally pass the `GRAPH_CONTAINER_NAME` env var if your neo4j container in docker has a different name. Defaults to `neo4j`.

- `true`: To set up the data in graph and reindex.
- `false`: To skip setting up database for test. (when you've already done so)
- `graph`: Only run the graph database mocks.
Then to run all tests:

```bash
cargo test
```

To test specific modules or features:

Expand All @@ -118,20 +122,7 @@ cargo bench --bench user get_user_view_by_id

## ⚠️ Troubleshooting

If tests or the development environment seem out of sync, follow these steps to reset:

1. **Reset Neo4j**:

```bash
docker exec neo4j bash -c "cypher-shell -u neo4j -p 12345678 'MATCH (n) DETACH DELETE n;'"
docker exec neo4j bash /db-graph/run-queries.sh
```

2. **Re-index Redis Cache**:

```bash
REINDEX=true cargo run
```
If tests or the development environment seem out of sync, follow the [Running Tests](#running-tests) steps to reload the mock data.

## 🌐 Useful Links

Expand Down
4 changes: 2 additions & 2 deletions benches/setup.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use pubky_nexus::{setup, Config};
use pubky_nexus::{Config, StackManager};
use std::{env, sync::Once};
use tokio::runtime::Runtime;

Expand All @@ -10,7 +10,7 @@ pub fn run_setup() {
env::set_var("RUST_LOG", "error");
rt.block_on(async {
let config = Config::from_env();
setup(&config).await;
StackManager::setup(&config).await;
});
});
}
4 changes: 2 additions & 2 deletions examples/from_file.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use anyhow::Result;
use pubky_nexus::{setup, types::DynError, Config, EventProcessor};
use pubky_nexus::{types::DynError, Config, EventProcessor, StackManager};
use std::fs::File;
use std::io::{self, BufRead};
use std::path::Path;
Expand All @@ -12,7 +12,7 @@ const FILE_PATH: &str = "examples/events.txt";
#[tokio::main]
async fn main() -> Result<(), DynError> {
let config = Config::from_env();
setup(&config).await;
StackManager::setup(&config).await;

let mut event_processor = EventProcessor::from_config(&config).await?;

Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@ pub use db::kv::traits::RedisOps;
pub use error::{Error, Result};
pub use events::processor::EventProcessor;
pub use reindex::reindex;
pub use setup::setup;
pub use setup::StackManager;

extern crate const_format;
80 changes: 80 additions & 0 deletions src/mock_db.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
use log::info;

use std::process::Stdio;

use neo4rs::query;

use pubky_nexus::{
db::connectors::redis::get_redis_conn, get_neo4j_graph, reindex, Config, StackManager,
};

#[tokio::main]
async fn main() {
let config = Config::from_env();
StackManager::setup(&config).await;
info!("Running mock db sync");
let args: Vec<String> = std::env::args().collect();
match args.get(1).map(String::as_str) {
Some("graph") => {
MockDB::sync_graph().await;
}
Some("redis") => {
MockDB::sync_redis().await;
}
None => {
MockDB::sync_graph().await;
MockDB::sync_redis().await;
}
Some(_) => {
panic!("Invalid argument. Use 'graph' or 'redis'");
}
}
}

pub struct MockDB {}

impl MockDB {
async fn sync_graph() {
let graph = get_neo4j_graph().expect("Failed to get Neo4j graph connection");

// drop and run the queries again
let drop_all_query = query("MATCH (n) DETACH DELETE n;");
graph
.lock()
.await
.run(drop_all_query)
.await
.expect("Could not drop graph nodes.");

let graph_env = std::env::var("GRAPH_CONTAINER_NAME").unwrap_or("neo4j".to_string());
// Run the run-queries.sh script on the Docker host using docker exec
tokio::process::Command::new("docker")
.args(&[
"exec",
graph_env.as_str(),
"bash",
"/db-graph/run-queries.sh",
])
.stdout(Stdio::inherit())
.stderr(Stdio::inherit())
.status()
.await
.expect("Failed to run run-queries.sh");
}

async fn sync_redis() {
// Drop all keys in Redis
let mut redis_conn = get_redis_conn()
.await
.expect("Could not get the redis connection");

redis::cmd("FLUSHALL")
.exec_async(&mut redis_conn)
.await
.expect("Failed to flush Redis");

// Reindex
info!("Starting reindexing process.");
reindex().await;
}
}
6 changes: 3 additions & 3 deletions src/models/post/details.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ impl PostDetails {

#[cfg(test)]
mod tests {
use crate::{setup, Config};
use crate::{Config, StackManager};

use super::*;

Expand All @@ -193,9 +193,9 @@ mod tests {

#[tokio_shared_rt::test(shared)]
async fn test_post_details_get_from_graph() {
// Open connections against ddbb
let config = Config::from_env();
setup(&config).await;
StackManager::setup(&config).await;

let _res = PostDetails::get_by_id(AUTHOR_A_ID, REPLY_ID).await.unwrap();
let replies = PostStream::get_post_replies(AUTHOR_A_ID, POST_ID, None, None, None)
.await
Expand Down
4 changes: 2 additions & 2 deletions src/models/user/details.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ impl UserDetails {

#[cfg(test)]
mod tests {
use crate::{setup, Config};
use crate::{Config, StackManager};

use super::*;

Expand All @@ -128,7 +128,7 @@ mod tests {
#[tokio_shared_rt::test(shared)]
async fn test_get_by_ids_from_redis() {
let config = Config::from_env();
setup(&config).await;
StackManager::setup(&config).await;

let user_details = UserDetails::get_by_ids(&USER_IDS).await.unwrap();
assert_eq!(user_details.len(), USER_IDS.len());
Expand Down
4 changes: 2 additions & 2 deletions src/service.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use log::info;
use pubky_nexus::{redis_is_empty, reindex, routes, setup, Config};
use pubky_nexus::{redis_is_empty, reindex, routes, Config, StackManager};
use tokio::net::TcpListener;

#[tokio::main]
async fn main() {
let config = Config::from_env();
setup(&config).await;
StackManager::setup(&config).await;

// Reindex if REINDEX is set to true or Redis is empty
let should_reindex = config.reindex || redis_is_empty().await.unwrap_or(false);
Expand Down
78 changes: 42 additions & 36 deletions src/setup.rs
Original file line number Diff line number Diff line change
@@ -1,47 +1,53 @@
use crate::config::Config;
use crate::db::connectors::{
neo4j::{Neo4jConnector, NEO4J_CONNECTOR},
redis::{RedisConnector, REDIS_CONNECTOR},
};
use crate::db::graph::setup::setup_graph;
use crate::{
db::connectors::{
neo4j::{Neo4jConnector, NEO4J_CONNECTOR},
redis::{RedisConnector, REDIS_CONNECTOR},
},
Config,
};
use log::{debug, info};

async fn setup_redis(config: &Config) {
let redis_connector = RedisConnector::new_connection(&config.redis_uri())
.await
.expect("Failed to connect to Redis");
pub struct StackManager {}

match REDIS_CONNECTOR.set(redis_connector) {
Err(e) => debug!("RedisConnector was already set: {:?}", e),
Ok(()) => info!("RedisConnector successfully set"),
}
}
impl StackManager {
async fn setup_redis(config: &Config) {
let redis_connector = RedisConnector::new_connection(&config.redis_uri())
.await
.expect("Failed to connect to Redis");

async fn setup_neo4j(config: &Config) {
let neo4j_connector = Neo4jConnector::new_connection(
&config.neo4j_uri(),
&config.neo4j_username,
&config.neo4j_password,
)
.await
.expect("Failed to connect to Neo4j");

match NEO4J_CONNECTOR.set(neo4j_connector) {
Err(e) => debug!("Neo4jConnector was already set: {:?}", e),
Ok(()) => info!("Neo4jConnector successfully set"),
match REDIS_CONNECTOR.set(redis_connector) {
Err(e) => debug!("RedisConnector was already set: {:?}", e),
Ok(()) => info!("RedisConnector successfully set"),
}
}

// Set Neo4J graph data constraints
setup_graph().await.unwrap_or_default();
}
async fn setup_neo4j(config: &Config) {
let neo4j_connector = Neo4jConnector::new_connection(
&config.neo4j_uri(),
&config.neo4j_username,
&config.neo4j_password,
)
.await
.expect("Failed to connect to Neo4j");

match NEO4J_CONNECTOR.set(neo4j_connector) {
Err(e) => debug!("Neo4jConnector was already set: {:?}", e),
Ok(()) => info!("Neo4jConnector successfully set"),
}

pub async fn setup(config: &Config) {
match env_logger::try_init() {
Ok(_) => info!("Env logger initiated"),
Err(err) => debug!("Env logger was already set: {}", err),
// Set Neo4J graph data constraints
setup_graph().await.unwrap_or_default();
}

// Initialize Redis and Neo4j
setup_redis(config).await;
setup_neo4j(config).await;
pub async fn setup(config: &Config) {
match env_logger::try_init() {
Ok(_) => info!("Env logger initiated"),
Err(err) => debug!("Env logger was already set: {}", err),
}

// Initialize Redis and Neo4j
Self::setup_redis(config).await;
Self::setup_neo4j(config).await;
}
}
5 changes: 3 additions & 2 deletions src/watcher.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
use log::error;
use log::info;
use pubky_nexus::PubkyConnector;
use pubky_nexus::{setup, Config, EventProcessor};
use pubky_nexus::{Config, EventProcessor, StackManager};
use tokio::time::{sleep, Duration};

/// Watches over a homeserver `/events` and writes into the Nexus databases
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Sync + Send>> {
let config = Config::from_env();
setup(&config).await;
StackManager::setup(&config).await;

PubkyConnector::initialise(&config, None)?;
let mut event_processor = EventProcessor::from_config(&config).await?;

Expand Down
Loading

0 comments on commit f0a81f3

Please sign in to comment.