use std::pin::Pin;
use std::sync::Arc;
use std::task::{Context, Poll};
use futures_util::{Future, Stream, StreamExt};
use pin_project::pin_project;
use tokio::sync::{OwnedSemaphorePermit, Semaphore, TryAcquireError, watch};
use tokio::time::Interval;
use tokio_stream::wrappers::BroadcastStream;
pub fn stop_channel() -> (StopHandle, ServerHandle) {
let (tx, rx) = tokio::sync::watch::channel(());
(StopHandle::new(rx), ServerHandle::new(tx))
}
#[derive(Debug, Clone)]
pub struct StopHandle(watch::Receiver<()>);
impl StopHandle {
pub(crate) fn new(rx: watch::Receiver<()>) -> Self {
Self(rx)
}
pub async fn shutdown(mut self) {
let _ = self.0.changed().await;
}
}
#[derive(Debug, Copy, Clone, thiserror::Error)]
#[error("The server is already stopped")]
pub struct AlreadyStoppedError;
#[derive(Debug, Clone)]
pub struct ServerHandle(Arc<watch::Sender<()>>);
impl ServerHandle {
pub(crate) fn new(tx: watch::Sender<()>) -> Self {
Self(Arc::new(tx))
}
pub fn stop(&self) -> Result<(), AlreadyStoppedError> {
self.0.send(()).map_err(|_| AlreadyStoppedError)
}
pub async fn stopped(self) {
self.0.closed().await
}
pub fn is_stopped(&self) -> bool {
self.0.is_closed()
}
}
#[derive(Clone, Debug)]
pub struct ConnectionGuard {
inner: Arc<Semaphore>,
max: usize,
}
impl ConnectionGuard {
pub fn new(limit: usize) -> Self {
Self { inner: Arc::new(Semaphore::new(limit)), max: limit }
}
pub fn try_acquire(&self) -> Option<ConnectionPermit> {
match self.inner.clone().try_acquire_owned() {
Ok(guard) => Some(guard),
Err(TryAcquireError::Closed) => unreachable!("Semaphore::Close is never called and can't be closed; qed"),
Err(TryAcquireError::NoPermits) => None,
}
}
pub fn available_connections(&self) -> usize {
self.inner.available_permits()
}
pub fn max_connections(&self) -> usize {
self.max
}
}
pub type ConnectionPermit = OwnedSemaphorePermit;
#[pin_project]
pub(crate) struct IntervalStream(#[pin] Option<tokio_stream::wrappers::IntervalStream>);
impl IntervalStream {
pub(crate) fn pending() -> Self {
Self(None)
}
pub(crate) fn new(interval: Interval) -> Self {
Self(Some(tokio_stream::wrappers::IntervalStream::new(interval)))
}
}
impl Stream for IntervalStream {
type Item = tokio::time::Instant;
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
if let Some(mut stream) = self.project().0.as_pin_mut() {
stream.poll_next_unpin(cx)
} else {
Poll::Pending
}
}
}
#[derive(Debug, Clone)]
pub(crate) struct SessionClose(tokio::sync::broadcast::Sender<()>);
impl SessionClose {
pub(crate) fn close(self) {
let _ = self.0.send(());
}
pub(crate) fn closed(&self) -> SessionClosedFuture {
SessionClosedFuture(BroadcastStream::new(self.0.subscribe()))
}
}
#[derive(Debug)]
pub struct SessionClosedFuture(BroadcastStream<()>);
impl Future for SessionClosedFuture {
type Output = ();
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
match self.0.poll_next_unpin(cx) {
Poll::Pending => Poll::Pending,
Poll::Ready(_) => Poll::Ready(()),
}
}
}
pub(crate) fn session_close() -> (SessionClose, SessionClosedFuture) {
let (tx, rx) = tokio::sync::broadcast::channel(1);
(SessionClose(tx), SessionClosedFuture(BroadcastStream::new(rx)))
}