fastcgi-client 0.7.0

Fastcgi client implemented for Rust.
Documentation
use crate::{ClientError, ClientResult};
use std::{collections::HashSet, time::Duration};
use tokio::{
    sync::Mutex,
    time::{sleep, timeout},
};

const MAX_REQUEST_ID: u16 = u16::max_value() - 1;

pub(crate) struct RequestIdGenerator {
    id: Mutex<u16>,
    ids: Mutex<HashSet<u16>>,
    timeout: Duration,
}

impl RequestIdGenerator {
    pub(crate) fn new(timeout: Duration) -> Self {
        Self {
            id: Mutex::new(0),
            ids: Default::default(),
            timeout,
        }
    }

    pub(crate) async fn alloc(&self) -> ClientResult<u16> {
        timeout(self.timeout, self.inner_alloc())
            .await
            .map_err(|_| ClientError::RequestIdGenerateTimeout)
    }

    async fn inner_alloc(&self) -> u16 {
        let mut id = self.id.lock().await;

        loop {
            if *id >= MAX_REQUEST_ID {
                *id = 0;
            }
            *id += 1;

            let ids = self.ids.lock().await;
            if ids.contains(&id) {
                drop(ids);
                sleep(Duration::from_millis(10)).await;
            } else {
                break;
            }
        }

        *id
    }

    pub(crate) async fn release(&self, id: u16) {
        self.ids.lock().await.remove(&id);
    }
}