cartel-pg 0.22.0

Async PostgreSQL driver for the dope runtime
Documentation
use crate::{api, protocol, reply::Error, schema};
use api::{ops::Query, task::lease::Target, traits};
use dope_fiber::{abi, context, wait};
use std::task;
use traits::sealed::Sealed;

pub struct Status<'app, 'g, 'r, 's, 'b, 'c, 'd: 'app, B: ?Sized, I, const ID: u8 = 0>(
    pub(in crate::api) Query<'app, 'g, 'r, 's, 'b, 'c, 'd, B, I, ID>,
)
where
    I: schema::QuerySet + 'd;

#[pin_project::pin_project]
struct Wait<'app, 'g, 'r, 's, 'b, 'c, 'd: 'app, B: ?Sized, I: schema::QuerySet + 'd, const ID: u8> {
    client: api::Client<'app, 'g, 'r, 's, 'b, 'c, 'd, B, I, ID>,
    expected: usize,
    #[pin]
    waiter: wait::Waiter<'app, 'd>,
}

impl<'app, 'g, 'r, 's, 'b, 'c, 'd: 'app, B: ?Sized, I: schema::QuerySet + 'd, const ID: u8>
    abi::Fiber<'d> for Wait<'app, 'g, 'r, 's, 'b, 'c, 'd, B, I, ID>
{
    type Output = Result<(), crate::reply::Error<'d, ID>>;

    fn poll(call: context::PollCall<'_, '_, 'd, Self>) -> task::Poll<Self::Output> {
        let (this, context) = call.into_parts();
        let this = this.project();
        let waiter = this.waiter.as_ref();
        let shared = &this.client.port.shared;
        if let Some(error) = shared.signals.failure() {
            waiter.unregister();
            return task::Poll::Ready(Err(error));
        }
        if shared.ready.count() == *this.expected {
            waiter.unregister();
            return task::Poll::Ready(Ok(()));
        }
        match shared.ready.try_register(waiter, context.as_ref()) {
            Ok(()) => task::Poll::Pending,
            Err(error) => {
                waiter.unregister();
                task::Poll::Ready(Err(crate::reply::Error::Wait(error)))
            }
        }
    }
}

impl<B: ?Sized, I: schema::QuerySet, const ID: u8> Copy
    for Status<'_, '_, '_, '_, '_, '_, '_, B, I, ID>
{
}

impl<B: ?Sized, I: schema::QuerySet, const ID: u8> Clone
    for Status<'_, '_, '_, '_, '_, '_, '_, B, I, ID>
{
    fn clone(&self) -> Self {
        *self
    }
}

impl<B: ?Sized, I: schema::QuerySet, const ID: u8> Sealed
    for Status<'_, '_, '_, '_, '_, '_, '_, B, I, ID>
{
}

impl<'app, 'g, 'r, 's, 'b, 'c, 'd: 'app, B: ?Sized, I: schema::QuerySet + 'd, const ID: u8>
    traits::Status<'d, ID> for Status<'app, 'g, 'r, 's, 'b, 'c, 'd, B, I, ID>
{
    fn backend_pid(self) -> Option<i32> {
        let target = self.0.target?;
        self.0
            .client
            .port
            .connection()
            .backend_pid(target.connection())
    }

    fn is_failed(self) -> bool {
        self.0.client.port.shared.signals.is_failed()
    }

    fn is_ready(self) -> bool {
        self.0.client.port.shared.ready.count() != 0
    }

    fn live_count(self) -> usize {
        self.0.client.port.shared.ready.count()
    }

    fn wait_ready(self) -> impl abi::Fiber<'d, Output = Result<(), Error<'d, ID>>> {
        let client = self.0.client;
        Wait {
            client,
            expected: client.port.capacity(),
            waiter: wait::Waiter::new(),
        }
    }

    fn set_policy(self, policy: protocol::PickPolicy) {
        self.0.client.port.shared.ready.set_policy(policy);
    }
}