cartel-pg 0.31.0

Async PostgreSQL driver for the dope runtime
use cartel_core::reply::order::Front;
use dope::manifold::client::session::response::work;

use crate::{
    api::results::group::Position,
    port::{replies, replies::Kind},
    protocol::{
        self,
        logic::{state, turn::Turn},
        runtime::tx::poll,
    },
    schema,
};

pub(super) enum Progress {
    Complete,
    Blocked,
}

enum Action {
    Done,
    Complete,
    Retire,
    FailGroup,
    FailOne,
}

impl<'turn, 'life, 'e, 'g, 'r, 's, 'b, 'c, 'd: 'life, I: schema::QuerySet, const ID: u8>
    Turn<'turn, 'life, 'e, 'g, 'r, 's, 'b, 'c, 'd, I, ID>
{
    pub(super) fn try_settle<A: work::Admission>(
        self,
        status: poll::Status,
        work: &mut A,
    ) -> Result<Progress, crate::Error> {
        let lane = self
            .port
            .responses(self.conn)
            .ok_or(crate::Error::Protocol(protocol::Reason::ReadyUnknown))?;
        let complete = loop {
            let action = lane.inspect(self.state.batch, self.region, |end, front| {
                if matches!(self.state.progress, state::Progress::Complete) {
                    if !matches!(
                        end,
                        Some(Kind::Ready | Kind::Begin | Kind::Commit | Kind::Sync(_))
                    ) {
                        return Err(crate::Error::Protocol(protocol::Reason::ReadyUnknown));
                    }
                    return Ok(work.admit(|| Action::Complete));
                }
                let Some(end) = end else {
                    return Ok(work::Capacity::Available(Action::Done));
                };
                if let Kind::Sync(group) = end {
                    if matches!(self.state.progress, state::Progress::Running) {
                        return Err(crate::Error::Protocol(protocol::Reason::ReadyUnknown));
                    }
                    return Ok(work.admit(|| {
                        if matches!(self.state.progress, state::Progress::Unknown) {
                            group.resolve(Position::Sync);
                        }
                        Action::Complete
                    }));
                }
                let command = match self.state.progress {
                    state::Progress::Skipping => None,
                    state::Progress::Unknown => match end {
                        Kind::Group(index, group) | Kind::Last(index, group) => {
                            Some((group, Position::Command(index as usize)))
                        }
                        Kind::Command
                        | Kind::Ready
                        | Kind::Begin
                        | Kind::Commit
                        | Kind::Sync(_) => {
                            return Err(crate::Error::Protocol(protocol::Reason::GroupReply));
                        }
                    },
                    state::Progress::Running | state::Progress::Complete => {
                        return Err(crate::Error::Protocol(protocol::Reason::ReadyUnknown));
                    }
                };
                Ok(work.admit(|| {
                    let server = command.is_some_and(|(group, position)| group.resolve(position));
                    if matches!(front, Front::Detached) {
                        Action::Retire
                    } else if server {
                        Action::FailGroup
                    } else {
                        Action::FailOne
                    }
                }))
            })?;
            match action? {
                work::Capacity::Available(Action::Done) => break false,
                work::Capacity::Available(Action::Complete) => break true,
                work::Capacity::Available(Action::Retire) => {
                    lane.complete(self.region);
                }
                work::Capacity::Available(Action::FailGroup) => {
                    lane.fail_group(self.region);
                }
                work::Capacity::Available(Action::FailOne) => lane.fail_one(
                    self.region,
                    replies::Failure::from_error(crate::Error::Skipped),
                ),
                work::Capacity::Exhausted(()) => return Ok(Progress::Blocked),
            }
        };
        let load = lane.settle(complete, self.region)?;
        self.state.progress = state::Progress::Running;
        self.state.batch = self.state.batch.next();
        if let Some(load) = load
            && matches!(
                self.port
                    .shared
                    .transaction()
                    .poll_ready(self.conn, status, load),
                poll::Readiness::Pending
            )
        {
            return Err(crate::Error::Protocol(protocol::Reason::TransactionOpen));
        }
        Ok(Progress::Complete)
    }
}