#![feature(async_closure)] #![feature(btree_cursors)] #![feature(let_chains)] mod ack; mod processor; pub mod range_map; use std::time::Duration; use anyhow::{anyhow, Result}; use lapin::{options::BasicPublishOptions, publisher_confirm::Confirmation, topology::{BindingDefinition, ExchangeDefinition, QueueDefinition, TopologyDefinition}, types::FieldTable, BasicProperties, Channel, Connection, ConnectionProperties}; use rand::{Rng, thread_rng}; use serde::{Deserialize, Serialize}; use tokio::{signal, time::sleep}; use crate::processor::Processor; static QUEUE_COUNT: usize = 10; static SEND_COUNT: usize = 100_000; #[tokio::main] async fn main() -> Result<()> { let quit_signal = signal::ctrl_c(); let conn = broker_connect().await?; let _ = conn.restore(TopologyDefinition { exchanges: vec![ ExchangeDefinition { name: "hello".into(), kind: None, options: None, arguments: None, bindings: vec![] }, ], queues: (0..QUEUE_COUNT).map(|i| QueueDefinition { name: format!("hello-{}", i).into(), options: None, arguments: None, bindings: vec![ BindingDefinition { source: "hello".into(), routing_key: "".into(), arguments: FieldTable::default(), }, ] } ).collect(), channels: vec![], }).await?; tokio::try_join!( tokio::spawn(async { let mut proc = Processor::new(broker_connect().await?, 65_535).await?; for i in 0..QUEUE_COUNT { proc.listen(&format!("hello-{}", i), &format!("processor-{}", i), move |data| process(data, i)).await?; } quit_signal.await.unwrap(); proc.shutdown().await }), tokio::spawn(async { let chan = conn.create_channel().await?; sender(conn, chan).await }), )?; Ok(()) } async fn broker_connect() -> lapin::Result { Connection::connect( "amqp://localhost", ConnectionProperties::default() .with_executor(tokio_executor_trait::Tokio::current()) .with_reactor(tokio_reactor_trait::Tokio), ).await } #[derive(Serialize, Deserialize)] struct Test { int: usize } async fn sender(conn: Connection, chan: Channel) -> lapin::Result<()> { for int in 0..SEND_COUNT { if int % 1000 == 0 { println!("Sending {}", int) }; let payload = Test { int }; let confirm = chan.basic_publish( "hello", "", BasicPublishOptions::default(), &serde_json::to_vec(&payload).unwrap(), BasicProperties::default(), ).await?.await?; assert_eq!(confirm, Confirmation::NotRequested); } conn.close(0, "").await?; println!("Done sending"); Ok(()) } async fn process(_test: Test, _i: usize) -> Result<()> { let (dur, fail) = { let mut rng = thread_rng(); (Duration::from_millis(rng.gen_range(1000..10000)), rng.gen_bool(0.01)) }; sleep(dur).await; //if fail { println!("{} Fail {} {:?}", _i, _test.int, dur); } if fail { Err(anyhow!("oops")) } else { Ok(()) } }