cartel-pg 0.22.0

Async PostgreSQL driver for the dope runtime
Documentation
use crate::reply::Error;
use crate::{api, schema};
use api::{Response, request, task};
use dope::{
    core::driver::{route::KeyTag, schedule::clock::timer},
    manifold::client::conn,
};
use dope_fiber::{abi, context, wait};
use std::{pin, task::Poll};
use task::lease::{Lease, Recover};

#[pin_project::pin_project]
pub(in crate::api) struct Stateful<'app, 'g, 'r, 's, 'b, 'c, 'd: 'app, B: ?Sized, I, const ID: u8>
where
    I: schema::QuerySet + 'd,
{
    command: task::Core<
        'app,
        'g,
        'r,
        's,
        'b,
        'c,
        'd,
        B,
        I,
        Response<'app, 'g, 'r, 's, 'b, 'c, 'd, api::ExtractUnit<ID>>,
        ID,
        (),
        conn::Id<'d, KeyTag<ID>>,
        Recover,
    >,
    #[pin]
    deadline: Result<timer::Alarm<'d>, timer::Exhausted>,
    #[pin]
    waiter: wait::Waiter<'app, 'd>,
}

impl<'app, 'g, 'r, 's, 'b, 'c, 'd: 'app, B: ?Sized, I: schema::QuerySet + 'd, const ID: u8>
    Stateful<'app, 'g, 'r, 's, 'b, 'c, 'd, B, I, ID>
{
    pub(in crate::api) fn new(
        client: api::Client<'app, 'g, 'r, 's, 'b, 'c, 'd, B, I, ID>,
        target: Option<api::Target<'d, ID>>,
        req: request::Request<'_>,
    ) -> Self {
        let core = client
            .raw_core_as::<api::ExtractUnit<ID>, conn::Id<'d, KeyTag<ID>>, Recover>(target, req);
        let guard = core.guard();
        Self {
            command: core,
            deadline: guard,
            waiter: wait::Waiter::new(),
        }
    }
}

impl<'app, 'g, 'r, 's, 'b, 'c, 'd: 'app, B: ?Sized, I: schema::QuerySet + 'd, const ID: u8>
    abi::Fiber<'d> for Stateful<'app, 'g, 'r, 's, 'b, 'c, 'd, B, I, ID>
{
    type Output = Result<
        Lease<'app, 'g, 'r, 's, 'b, 'c, 'd, B, I, conn::Id<'d, KeyTag<ID>>, Recover, ID>,
        Error<'d, ID>,
    >;

    fn poll(call: context::PollCall<'_, '_, 'd, Self>) -> Poll<Self::Output> {
        let (this, mut ctx) = call.into_parts();
        let mut this = this.project();
        let mut guard = match this.deadline.as_mut().get_mut() {
            Ok(guard) => pin::Pin::new(guard),
            Err(error) => {
                this.waiter.as_ref().unregister();
                return Poll::Ready(Err(this.command.no_timer(*error)));
            }
        };
        let phase = this.command.phase();
        if let Poll::Ready(time) = this.command.poll_time(guard.as_mut(), ctx.as_mut(), phase) {
            this.waiter.as_ref().unregister();
            return Poll::Ready(Err(this.command.expire(time)));
        }
        match this
            .command
            .poll_done(ctx.as_mut(), this.waiter.as_ref(), Lease::admit)
        {
            Poll::Pending => Poll::Pending,
            Poll::Ready(task::Done::AdmissionFailed(error)) => {
                guard.as_ref().clear();
                Poll::Ready(Err(error))
            }
            Poll::Ready(task::Done::Response {
                outcome: Ok(()),
                committed: lease,
            }) => {
                guard.as_ref().clear();
                Poll::Ready(Ok(lease))
            }
            Poll::Ready(task::Done::Response {
                outcome: Err(error),
                committed: lease,
            }) => {
                lease.settle();
                guard.as_ref().clear();
                Poll::Ready(Err(error))
            }
        }
    }
}