Skip to content

Commit

Permalink
feat(snot): support multiple tests
Browse files Browse the repository at this point in the history
  • Loading branch information
gluax committed Mar 23, 2024
1 parent 38f8f85 commit 91405a5
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 20 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 7 additions & 4 deletions crates/snot/src/server/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub(super) fn routes() -> Router<AppState> {
.route("/storage/:id/:ty", get(redirect_storage))
.route("/agents", get(get_agents))
.route("/test/prepare", post(post_test_prepare))
.route("/test", delete(delete_test))
.route("/test/:id", delete(delete_test))
}

#[derive(Deserialize)]
Expand Down Expand Up @@ -67,7 +67,7 @@ async fn post_test_prepare(state: State<AppState>, body: String) -> Response {
// TODO: support concurrent tests + return test id

match Test::prepare(documents, &state).await {
Ok(_) => StatusCode::OK.into_response(),
Ok(test_id) => (StatusCode::OK, Json(json!({ "id": test_id }))).into_response(),
Err(e) => (
StatusCode::INTERNAL_SERVER_ERROR,
Json(json!({ "error": format!("{e}") })),
Expand All @@ -76,8 +76,11 @@ async fn post_test_prepare(state: State<AppState>, body: String) -> Response {
}
}

async fn delete_test(State(state): State<AppState>) -> impl IntoResponse {
match Test::cleanup(&state).await {
async fn delete_test(
Path(test_id): Path<usize>,
State(state): State<AppState>,
) -> impl IntoResponse {
match Test::cleanup(&test_id, &state).await {
Ok(_) => StatusCode::OK.into_response(),
Err(e) => (
StatusCode::INTERNAL_SERVER_ERROR,
Expand Down
3 changes: 2 additions & 1 deletion crates/snot/src/server/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ pub async fn start(cli: Cli) -> Result<()> {
cli,
pool: Default::default(),
storage: Default::default(),
test: Default::default(),
tests_counter: Default::default(),
tests: Default::default(),
};

let app = Router::new()
Expand Down
5 changes: 3 additions & 2 deletions crates/snot/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,9 @@ pub struct GlobalState {
pub pool: RwLock<HashMap<AgentId, Agent>>,
/// A map from ephemeral integer storage ID to actual storage ID.
pub storage: RwLock<BiMap<usize, String>>,
// TODO: support concurrent tests
pub test: RwLock<Option<Test>>,

pub tests_counter: AtomicUsize,
pub tests: RwLock<HashMap<usize, Test>>,
}

/// This is the representation of a public addr or a list of internal addrs.
Expand Down
33 changes: 20 additions & 13 deletions crates/snot/src/testing.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::sync::atomic::Ordering;

use anyhow::{anyhow, bail, ensure};
use bimap::BiMap;
use futures_util::future::join_all;
Expand Down Expand Up @@ -54,10 +56,11 @@ impl Test {
///
/// **This will error if the current test is not unset before calling to
/// ensure tests are properly cleaned up.**
pub async fn prepare(documents: Vec<ItemDocument>, state: &GlobalState) -> anyhow::Result<()> {
ensure!(state.test.read().await.is_none());

let mut state_lock = state.test.write().await;
pub async fn prepare(
documents: Vec<ItemDocument>,
state: &GlobalState,
) -> anyhow::Result<usize> {
let mut state_lock = state.tests.write().await;

let Some(storage_id) = documents.iter().find_map(|s| match s {
ItemDocument::Storage(storage) => Some(storage.id.clone()),
Expand Down Expand Up @@ -152,23 +155,25 @@ impl Test {
}

// set the test on the global state
*state_lock = Some(test);

let test_id = state.tests_counter.fetch_add(1, Ordering::Relaxed);
state_lock.insert(test_id, test);
drop(state_lock);

// reconcile the nodes
initial_reconcile(state).await?;
initial_reconcile(&test_id, state).await?;

Ok(())
Ok(test_id)
}

// TODO: cleanup by test id, rather than cleanup EVERY agent...

pub async fn cleanup(state: &GlobalState) -> anyhow::Result<()> {
pub async fn cleanup(id: &usize, state: &GlobalState) -> anyhow::Result<()> {
// clear the test state
{
info!("clearing test state...");
let mut state_lock = state.test.write().await;
*state_lock = None;
let mut state_lock = state.tests.write().await;
state_lock.remove(id);
}

// reconcile all online agents
Expand Down Expand Up @@ -219,12 +224,14 @@ impl Test {
}

/// Reconcile all associated nodes with their initial state.
pub async fn initial_reconcile(state: &GlobalState) -> anyhow::Result<()> {
pub async fn initial_reconcile(id: &usize, state: &GlobalState) -> anyhow::Result<()> {
let mut handles = vec![];
let mut agent_ids = vec![];
{
let test_lock = state.test.read().await;
let test = test_lock.as_ref().unwrap();
let tests_lock = state.tests.read().await;
let test = tests_lock
.get(id)
.ok_or_else(|| anyhow!("test not found"))?;

// get the numeric storage ID from the string storage ID
let storage_id = {
Expand Down

0 comments on commit 91405a5

Please sign in to comment.