refactor: one channel per consumer
This commit is contained in:
@@ -108,5 +108,5 @@ pub async fn client_subscriber(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
consumer.dispose().await;
|
consumer.dispose_channel().await;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,18 +5,21 @@ use std::{
|
|||||||
|
|
||||||
use async_std::stream::StreamExt;
|
use async_std::stream::StreamExt;
|
||||||
use lapin::{
|
use lapin::{
|
||||||
Channel,
|
Channel, Connection,
|
||||||
options::BasicAckOptions,
|
options::BasicAckOptions,
|
||||||
types::{AMQPValue, FieldArray, FieldTable, LongLongInt},
|
types::{AMQPValue, FieldArray, FieldTable, LongLongInt},
|
||||||
};
|
};
|
||||||
|
use log::info;
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use revolt_config::config;
|
use revolt_config::{capture_internal_error, config};
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
|
|
||||||
use crate::event_stream::get_channel;
|
use crate::event_stream::{create_channel, get_connection};
|
||||||
|
|
||||||
pub struct Consumer {
|
pub struct Consumer {
|
||||||
channel: Arc<Channel>,
|
#[allow(dead_code)]
|
||||||
|
conn: Arc<Connection>,
|
||||||
|
channel: Channel,
|
||||||
tag: String,
|
tag: String,
|
||||||
topics: HashSet<String>,
|
topics: HashSet<String>,
|
||||||
topics_changed: bool,
|
topics_changed: bool,
|
||||||
@@ -27,8 +30,13 @@ pub struct Consumer {
|
|||||||
impl Consumer {
|
impl Consumer {
|
||||||
/// Create a new event stream consumer
|
/// Create a new event stream consumer
|
||||||
pub async fn new() -> Consumer {
|
pub async fn new() -> Consumer {
|
||||||
|
let config = config().await;
|
||||||
|
let conn = get_connection().await;
|
||||||
|
let channel = create_channel(&conn, config.rabbit.event_stream).await;
|
||||||
|
|
||||||
Consumer {
|
Consumer {
|
||||||
channel: get_channel().await,
|
conn,
|
||||||
|
channel,
|
||||||
tag: rand::rng()
|
tag: rand::rng()
|
||||||
.sample_iter::<char, _>(&rand::distr::StandardUniform)
|
.sample_iter::<char, _>(&rand::distr::StandardUniform)
|
||||||
.take(32)
|
.take(32)
|
||||||
@@ -49,10 +57,13 @@ impl Consumer {
|
|||||||
/// Get the current consumer
|
/// Get the current consumer
|
||||||
pub async fn ensure_consumer(&mut self) {
|
pub async fn ensure_consumer(&mut self) {
|
||||||
if self.topics_changed {
|
if self.topics_changed {
|
||||||
self.consumer = None;
|
info!("Topics changed, disposing the consumer.");
|
||||||
|
self.dispose_consumer().await;
|
||||||
|
self.topics_changed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.consumer.is_none() {
|
if self.consumer.is_none() {
|
||||||
|
info!("Creating a new consumer, tag={}", self.tag);
|
||||||
let config = config().await;
|
let config = config().await;
|
||||||
|
|
||||||
// Build arguments for consumer
|
// Build arguments for consumer
|
||||||
@@ -88,27 +99,36 @@ impl Consumer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Close the active consumer
|
/// Close the active consumer if one exists
|
||||||
pub async fn dispose(&mut self) {
|
pub async fn dispose_consumer(&mut self) {
|
||||||
// Close the channel -- don't do this actually
|
if let Some(consumer) = self.consumer.as_ref() {
|
||||||
// capture_internal_error!(self.channel.close(0, "closing channel").await);
|
if consumer.state().is_active() {
|
||||||
|
if let Err(err) = self
|
||||||
|
.channel
|
||||||
|
.basic_cancel(&self.tag, Default::default())
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
eprintln!("Failed to close consumer! {:?}", err);
|
||||||
|
}
|
||||||
|
|
||||||
// Close the consumer
|
// is this necessary?
|
||||||
if let Err(err) = self
|
// else {
|
||||||
.channel
|
// Read the consumer to the end
|
||||||
.basic_cancel(&self.tag, Default::default())
|
// while let Some(delivery) = consumer.next().await {
|
||||||
.await
|
// let delivery = delivery.expect("error in consumer");
|
||||||
{
|
// delivery.ack(BasicAckOptions::default()).await.expect("ack");
|
||||||
eprintln!("Failed to close consumer! {:?}", err);
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
self.consumer = None;
|
||||||
}
|
}
|
||||||
// is this necessary?
|
}
|
||||||
// else {
|
|
||||||
// Read the consumer to the end
|
/// Close the active channel
|
||||||
// while let Some(delivery) = consumer.next().await {
|
pub async fn dispose_channel(&mut self) {
|
||||||
// let delivery = delivery.expect("error in consumer");
|
// Close the channel -- don't do this actually
|
||||||
// delivery.ack(BasicAckOptions::default()).await.expect("ack");
|
capture_internal_error!(self.channel.close(0, "closing channel").await);
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the next item
|
/// Get the next item
|
||||||
|
|||||||
@@ -3,5 +3,5 @@ mod pool;
|
|||||||
mod publish;
|
mod publish;
|
||||||
|
|
||||||
pub use consumer::Consumer;
|
pub use consumer::Consumer;
|
||||||
pub use pool::get_channel;
|
pub use pool::{create_channel, get_connection};
|
||||||
pub use publish::publish_event;
|
pub use publish::publish_event;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use async_std::sync::Mutex;
|
use async_std::sync::Mutex;
|
||||||
use lapin::{
|
use lapin::{
|
||||||
Channel,
|
Connection,
|
||||||
options::QueueDeclareOptions,
|
options::QueueDeclareOptions,
|
||||||
types::{AMQPValue, FieldTable},
|
types::{AMQPValue, FieldTable},
|
||||||
};
|
};
|
||||||
@@ -11,10 +11,10 @@ use std::sync::Arc;
|
|||||||
use crate::create_client;
|
use crate::create_client;
|
||||||
|
|
||||||
/// Get a handle to the event stream
|
/// Get a handle to the event stream
|
||||||
pub async fn get_channel() -> Arc<Channel> {
|
pub async fn get_connection() -> Arc<Connection> {
|
||||||
let config = config().await;
|
let config = config().await;
|
||||||
|
|
||||||
static CONNECTIONS: Mutex<Vec<Arc<lapin::Channel>>> = Mutex::new(Vec::new());
|
static CONNECTIONS: Mutex<Vec<Arc<Connection>>> = Mutex::new(Vec::new());
|
||||||
|
|
||||||
let mut connections = CONNECTIONS.lock().await;
|
let mut connections = CONNECTIONS.lock().await;
|
||||||
connections.retain(|item| {
|
connections.retain(|item| {
|
||||||
@@ -39,22 +39,21 @@ pub async fn get_channel() -> Arc<Channel> {
|
|||||||
.collect::<Vec<usize>>()
|
.collect::<Vec<usize>>()
|
||||||
);
|
);
|
||||||
|
|
||||||
for channel in connections.iter() {
|
for conn in connections.iter() {
|
||||||
if Arc::strong_count(channel) < config.rabbit.event_stream.channels_per_conn {
|
if Arc::strong_count(conn) < config.rabbit.event_stream.channels_per_conn {
|
||||||
return channel.clone();
|
return conn.clone();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let conn = create_client().await;
|
let conn = Arc::new(create_client().await);
|
||||||
let channel = Arc::new(create_channel(conn, config.rabbit.event_stream).await);
|
|
||||||
|
|
||||||
connections.push(channel.clone());
|
connections.push(conn.clone());
|
||||||
channel
|
conn
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a channel
|
/// Create a channel
|
||||||
async fn create_channel(
|
pub async fn create_channel(
|
||||||
conn: lapin::Connection,
|
conn: &lapin::Connection,
|
||||||
event_stream: RabbitEventStream,
|
event_stream: RabbitEventStream,
|
||||||
) -> lapin::Channel {
|
) -> lapin::Channel {
|
||||||
let channel = conn.create_channel().await.unwrap();
|
let channel = conn.create_channel().await.unwrap();
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use lapin::{
|
|||||||
use revolt_config::config;
|
use revolt_config::config;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
use crate::event_stream::get_channel;
|
use crate::event_stream::{create_channel, get_connection};
|
||||||
|
|
||||||
/// Publish an event to the message broker
|
/// Publish an event to the message broker
|
||||||
pub async fn publish_event<T: Serialize>(
|
pub async fn publish_event<T: Serialize>(
|
||||||
@@ -22,7 +22,9 @@ pub async fn publish_event<T: Serialize>(
|
|||||||
AMQPValue::LongString(channel.into()),
|
AMQPValue::LongString(channel.into()),
|
||||||
);
|
);
|
||||||
|
|
||||||
get_channel()
|
let conn = get_connection().await;
|
||||||
|
|
||||||
|
create_channel(&conn, config.rabbit.event_stream.clone())
|
||||||
.await
|
.await
|
||||||
.basic_publish(
|
.basic_publish(
|
||||||
&config.rabbit.event_stream.exchange,
|
&config.rabbit.event_stream.exchange,
|
||||||
|
|||||||
@@ -40,7 +40,9 @@ impl TestHarness {
|
|||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
static QUEUE_NAME: &str = "revolt.events";
|
static QUEUE_NAME: &str = "revolt.events";
|
||||||
let consumer = event_stream::get_channel()
|
let conn = event_stream::get_connection().await;
|
||||||
|
|
||||||
|
let consumer = event_stream::create_channel(&conn, config.rabbit.event_stream)
|
||||||
.await
|
.await
|
||||||
.basic_consume(QUEUE_NAME, &tag, Default::default(), Default::default())
|
.basic_consume(QUEUE_NAME, &tag, Default::default(), Default::default())
|
||||||
.await
|
.await
|
||||||
|
|||||||
Reference in New Issue
Block a user