102 lines
3.2 KiB
Rust
102 lines
3.2 KiB
Rust
#![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> {
|
|
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(()) }
|
|
}
|