escalon 0.1.17

UDP communication layer for the Escalon project
Documentation
mod builder;
mod constants;
mod implementations;
mod types;

use builder::{Manager, NoManager};
pub use tokio;

#[cfg(test)]
mod tests;

use async_trait::async_trait;
use local_ip_address::local_ip;
use std::collections::HashMap;
use std::net::SocketAddr;
use std::sync::{Arc, Mutex};
use tokio::net::UdpSocket;
use tokio::sync::mpsc::Sender;

use crate::builder::{Addr, Id, Port};
use crate::builder::{NoAddr, NoId, NoPort};
pub use crate::types::client::{ClientState, EscalonClient};
use crate::types::message::Message;

pub struct Distrib {
    pub client_id: String,
    pub take_from: String,
    pub start_at: usize,
    pub n_jobs: usize,
    pub done: bool,
}

#[async_trait]
pub trait EscalonTrait: Send + Sync + 'static {
    fn count(&self) -> usize;
    async fn take_jobs(
        &self,
        take_from: String,
        start_at: usize,
        n_jobs: usize,
    ) -> Result<Vec<String>, ()>;
    async fn drop_jobs(&self, jobs: Vec<String>) -> Result<(), ()>;
}

#[derive(Clone)]
pub struct Escalon {
    id: String,
    address: SocketAddr,
    start_time: std::time::SystemTime,
    pub clients: Arc<Mutex<HashMap<String, EscalonClient>>>,
    distribution: Arc<Mutex<Vec<Distrib>>>,
    manager: Arc<dyn EscalonTrait>,
    socket: Arc<UdpSocket>,
    tx_handler: Option<Sender<Message>>,
    tx_sender: Option<Sender<(Message, Option<SocketAddr>)>>,
}

impl Escalon {
    #[allow(clippy::new_ret_no_self)]
    pub fn new() -> EscalonBuilder<NoId, NoAddr, NoPort, NoManager> {
        EscalonBuilder {
            id: NoId,
            addr: NoAddr,
            port: NoPort,
            manager: NoManager,
        }
    }
}

pub struct EscalonBuilder<I, A, P, F> {
    id: I,
    addr: A,
    port: P,
    manager: F,
}

impl EscalonBuilder<Id, Addr, Port, Manager> {
    pub async fn build(self) -> Escalon {
        let socket =
            UdpSocket::bind(format!("{:?}:{}", self.addr.0, self.port.0)).await.unwrap();
        socket.set_broadcast(true).unwrap();

        Escalon {
            id: self.id.0,
            address: SocketAddr::new(local_ip().unwrap(), self.port.0),
            start_time: std::time::SystemTime::now(),
            manager: self.manager.0,
            clients: Arc::new(Mutex::new(HashMap::new())),
            distribution: Arc::new(Mutex::new(Vec::new())),
            socket: Arc::new(socket),
            tx_handler: None,
            tx_sender: None,
        }
    }
}