use std::sync::mpsc::{sync_channel, Receiver, SyncSender}; // TODO: Implement the patching functionality. use crate::data::{Ticket, TicketDraft, TicketPatch}; use crate::store::{TicketId, TicketStore}; pub mod data; pub mod store; #[derive(Clone)] pub struct TicketStoreClient { sender: SyncSender, } impl TicketStoreClient { pub fn insert(&self, draft: TicketDraft) -> Result { let (response_sender, response_receiver) = sync_channel(1); self.sender .try_send(Command::Insert { draft, response_channel: response_sender, }) .map_err(|_| OverloadedError)?; Ok(response_receiver.recv().unwrap()) } pub fn get(&self, id: TicketId) -> Result, OverloadedError> { let (response_sender, response_receiver) = sync_channel(1); self.sender .try_send(Command::Get { id, response_channel: response_sender, }) .map_err(|_| OverloadedError)?; Ok(response_receiver.recv().unwrap()) } pub fn update(&self, ticket_patch: TicketPatch) -> Result<(), OverloadedError> {} } #[derive(Debug, thiserror::Error)] #[error("The store is overloaded")] pub struct OverloadedError; pub fn launch(capacity: usize) -> TicketStoreClient { let (sender, receiver) = sync_channel(capacity); std::thread::spawn(move || server(receiver)); TicketStoreClient { sender } } enum Command { Insert { draft: TicketDraft, response_channel: SyncSender, }, Get { id: TicketId, response_channel: SyncSender>, }, Update { patch: TicketPatch, response_channel: SyncSender<()>, }, } pub fn server(receiver: Receiver) { let mut store = TicketStore::new(); loop { match receiver.recv() { Ok(Command::Insert { draft, response_channel, }) => { let id = store.add_ticket(draft); let _ = response_channel.send(id); } Ok(Command::Get { id, response_channel, }) => { let ticket = store.get(id); let _ = response_channel.send(ticket.cloned()); } Ok(Command::Update { patch, response_channel, }) => { todo!() } Err(_) => { // There are no more senders, so we can safely break // and shut down the server. break; } } } }