queuing things

This commit is contained in:
nora 2022-03-07 16:33:52 +01:00
parent 2fe3b4b77b
commit 770762b920
16 changed files with 102 additions and 13 deletions

6
Cargo.lock generated
View file

@ -36,6 +36,7 @@ dependencies = [
name = "amqp_core"
version = "0.1.0"
dependencies = [
"amqp_datastructure",
"bytes",
"parking_lot",
"rand",
@ -62,11 +63,16 @@ dependencies = [
"zip",
]
[[package]]
name = "amqp_datastructure"
version = "0.1.0"
[[package]]
name = "amqp_messaging"
version = "0.1.0"
dependencies = [
"amqp_core",
"amqp_datastructure",
"parking_lot",
"tokio",
"tracing",

View file

@ -1,5 +1,13 @@
[workspace]
members = [".", "amqp_core", "amqp_dashboard", "amqp_messaging", "amqp_transport","xtask"]
members = [
".",
"amqp_core",
"amqp_dashboard",
"amqp_datastructure",
"amqp_messaging",
"amqp_transport",
"xtask",
]
[package]
name = "amqp"

View file

@ -6,6 +6,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
amqp_datastructure = { path = "../amqp_datastructure" }
bytes = "1.1.0"
parking_lot = "0.12.0"
rand = "0.8.5"

View file

@ -47,7 +47,7 @@ impl Display for QueueName {
pub struct QueueInner {
pub id: QueueId,
pub name: QueueName,
pub messages: Mutex<Vec<Message>>, // use a concurrent linked list???
pub messages: amqp_datastructure::MessageQueue<Message>,
pub durable: bool,
pub exclusive: Option<ChannelId>,
/// Whether the queue will automatically be deleted when no consumers uses it anymore.

View file

@ -46,11 +46,12 @@ const DataPage: FC<Props> = ({ prefix }) => {
<h2>Queues</h2>
{data ? (
<Table
headers={['Queue ID', 'Name', 'Durable']}
headers={['Queue ID', 'Name', 'Durable', 'Message Count']}
rows={data.queues.map((queue) => [
queue.id,
queue.name,
queue.durable ? 'Yes' : 'No',
queue.messages,
])}
/>
) : (

View file

@ -13,6 +13,7 @@ export type Queue = {
id: string;
name: string;
durable: boolean;
messages: number;
};
export type Data = {

View file

@ -76,6 +76,7 @@ struct Queue {
id: String,
name: String,
durable: bool,
messages: usize,
}
async fn get_data(global_data: GlobalData) -> impl IntoResponse {
@ -106,6 +107,7 @@ async fn get_data(global_data: GlobalData) -> impl IntoResponse {
id: queue.id.to_string(),
name: queue.name.to_string(),
durable: queue.durable,
messages: queue.messages.len(),
})
.collect();

View file

@ -0,0 +1,8 @@
[package]
name = "amqp_datastructure"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

View file

@ -0,0 +1,3 @@
mod message_queue;
pub use message_queue::MessageQueue;

View file

@ -0,0 +1,57 @@
// using std::sync::Mutex because it's only temporary anyways
use std::{
collections::VecDeque,
fmt::{Debug, Formatter},
sync::Mutex,
};
/// The data structure behind the message queue.
///
/// Needs to support:
/// * concurrent access
/// * priority
///
/// Currently supports
/// * mutex lol
// todo: see above
pub struct MessageQueue<T> {
deque: Mutex<VecDeque<T>>,
}
impl<T> MessageQueue<T> {
pub fn new() -> Self {
Self {
deque: Mutex::default(),
}
}
pub fn append(&self, message: T) {
let mut lock = self.deque.lock().unwrap();
lock.push_back(message);
}
pub fn try_get(&self) -> Option<T> {
let mut lock = self.deque.lock().unwrap();
lock.pop_front()
}
pub fn len(&self) -> usize {
self.deque.lock().unwrap().len()
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}
impl<T> Default for MessageQueue<T> {
fn default() -> Self {
Self::new()
}
}
impl<T: Debug> Debug for MessageQueue<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("MessageQueue").finish_non_exhaustive()
}
}

View file

@ -7,6 +7,7 @@ edition = "2021"
[dependencies]
amqp_core = { path = "../amqp_core" }
amqp_datastructure = { path = "../amqp_datastructure" }
parking_lot = "0.12.0"
tracing = "0.1.31"
tokio = { version = "1.17.0", features = ["full"] }

View file

@ -4,13 +4,10 @@ mod queue;
use crate::Result;
use amqp_core::{amqp_todo, connection::Channel, message::Message, methods::Method};
use tracing::{error, info};
use tracing::info;
pub fn handle_basic_publish(channel_handle: Channel, message: Message) {
match publish::publish(channel_handle, message) {
Ok(()) => {}
Err(err) => error!(%err, "publish error occurred"),
}
pub fn handle_basic_publish(channel_handle: Channel, message: Message) -> Result<()> {
publish::publish(channel_handle, message)
}
pub async fn handle_method(channel_handle: Channel, method: Method) -> Result<Method> {

View file

@ -42,7 +42,7 @@ pub fn declare(channel: Channel, queue_declare: QueueDeclare) -> Result<Method>
let queue = Arc::new(QueueInner {
id,
name: queue_name.clone(),
messages: Mutex::default(),
messages: amqp_datastructure::MessageQueue::new(),
durable,
exclusive: exclusive.then(|| channel.id),
deletion: if auto_delete {

View file

@ -94,7 +94,9 @@ impl QueueTask {
}
#[tracing::instrument(skip(self), fields(name = self.show_name()), level = "trace")]
async fn queue_message(&mut self, _message: Message) {}
async fn queue_message(&mut self, message: Message) {
self.queue.messages.append(message);
}
async fn cleanup(&mut self) {
// do stuff or something like that id whatever

View file

@ -498,7 +498,7 @@ impl TransportConnection {
let channel = self.channels.get(&channel).ok_or(ConException::Todo)?;
amqp_messaging::methods::handle_basic_publish(channel.global_chan.clone(), message);
amqp_messaging::methods::handle_basic_publish(channel.global_chan.clone(), message)?;
Ok(())
} else {
Err(ConException::Todo.into())

View file

@ -3,7 +3,9 @@ import { connectAmqp } from './utils/utils.js';
const connection = await connectAmqp();
const channel = await connection.createChannel();
channel.publish('exchange-1', 'queue-1', Buffer.from('hello'));
await channel.assertQueue('send-queue-352');
channel.publish('', 'send-queue-352', Buffer.from('hello'));
console.log('Published message');