use std::sync::atomic::{AtomicU32, Ordering};
use std::sync::Arc;
use std::time::Duration;
use acton_reactive::prelude::*;
use acton_test::prelude::*;
#[acton_test]
async fn test_counter_state_example() -> anyhow::Result<()> {
#[acton_actor]
struct CounterState {
count: u32,
}
#[acton_message]
struct Increment(u32);
let final_count = Arc::new(AtomicU32::new(0));
let final_count_clone = final_count.clone();
let mut runtime = ActonApp::launch_async().await;
let mut counter = runtime.new_actor::<CounterState>();
counter
.mutate_on::<Increment>(|actor, ctx| {
actor.model.count += ctx.message().0;
Reply::ready()
})
.after_stop(move |actor| {
final_count_clone.store(actor.model.count, Ordering::SeqCst);
Reply::ready()
});
let handle = counter.start().await;
handle.send(Increment(1)).await;
handle.send(Increment(2)).await;
handle.send(Increment(3)).await;
tokio::time::sleep(Duration::from_millis(50)).await;
runtime.shutdown_all().await?;
assert_eq!(final_count.load(Ordering::SeqCst), 6);
Ok(())
}
#[acton_test]
async fn test_query_handler_example() -> anyhow::Result<()> {
#[acton_actor]
struct CounterState {
count: u32,
}
#[acton_actor]
struct CountClient {
counter_handle: Option<ActorHandle>,
}
#[acton_message]
struct Increment(u32);
#[acton_message]
struct QueryCount;
#[acton_message]
struct GetCount;
#[acton_message]
struct CountResponse(u32);
let received = Arc::new(AtomicU32::new(0));
let received_clone = received.clone();
let mut runtime = ActonApp::launch_async().await;
let mut counter = runtime.new_actor::<CounterState>();
counter.mutate_on::<Increment>(|actor, ctx| {
actor.model.count += ctx.message().0;
Reply::ready()
});
counter.act_on::<GetCount>(|actor, ctx| {
let count = actor.model.count;
let reply = ctx.reply_envelope();
Reply::pending(async move {
reply.send(CountResponse(count)).await;
})
});
let counter_handle = counter.start().await;
let mut client = runtime.new_actor::<CountClient>();
client.model.counter_handle = Some(counter_handle.clone());
client
.mutate_on::<QueryCount>(|actor, ctx| {
let target = actor.model.counter_handle.clone().unwrap();
let request_envelope = ctx.new_envelope(&target.reply_address());
Reply::pending(async move {
request_envelope.send(GetCount).await;
})
})
.mutate_on::<CountResponse>(move |_actor, ctx| {
received_clone.store(ctx.message().0, Ordering::SeqCst);
Reply::ready()
});
let client_handle = client.start().await;
counter_handle.send(Increment(5)).await;
counter_handle.send(Increment(3)).await;
client_handle.send(QueryCount).await;
tokio::time::sleep(Duration::from_millis(100)).await;
runtime.shutdown_all().await?;
assert_eq!(received.load(Ordering::SeqCst), 8);
Ok(())
}