liminal-server 0.19.1

Standalone server for the liminal messaging bus
Documentation
use super::handler::ProductionParticipantHandler;
use crate::server::participant::{
    ParticipantConnectionContext, ParticipantConnectionConversations, ParticipantSemanticError,
};
use liminal_protocol::wire::{
    BindingEpoch, RecordAdmission, RecordAdmissionResponse, ServerValue, SettlementAnswer,
    SettlementOutcome, SettlementQuery,
};

const fn answer(request: &SettlementQuery, outcome: SettlementOutcome) -> ServerValue {
    ServerValue::SettlementAnswer(SettlementAnswer {
        conversation_id: request.conversation_id,
        participant_id: request.participant_id,
        record_admission_attempt_token: request.record_admission_attempt_token,
        outcome,
    })
}

impl ProductionParticipantHandler {
    pub(super) fn answer_settlement_query(
        &self,
        context: ParticipantConnectionContext,
        conversations: &ParticipantConnectionConversations,
        request: &SettlementQuery,
    ) -> Result<ServerValue, ParticipantSemanticError> {
        let Some(cell) = self.existing_cell(request.conversation_id)? else {
            return Ok(answer(request, SettlementOutcome::Unknown));
        };
        let owner = cell
            .lock()
            .map_err(|_| ParticipantSemanticError::Internal {
                message: "participant settlement owner lock is poisoned".to_owned(),
            })?;
        let Some(authority) = owner.as_ref() else {
            drop(owner);
            return Ok(answer(request, SettlementOutcome::Unknown));
        };
        let facts = self.operation_facts(context, request.conversation_id, conversations)?;
        let admission = RecordAdmission {
            conversation_id: request.conversation_id,
            participant_id: request.participant_id,
            capability_generation: request.capability_generation,
            record_admission_attempt_token: request.record_admission_attempt_token,
            payload: Vec::new(),
        };
        let receiving_epoch =
            BindingEpoch::new(facts.receiving_incarnation, request.capability_generation);
        if let Some(outcome) =
            authority.classify_record_admission_authority(&admission, &facts, receiving_epoch)
        {
            drop(owner);
            return Ok(outcome.value);
        }
        let token = request.record_admission_attempt_token.into_bytes();
        let key = (token, request.participant_id, request.payload_fingerprint);
        if let Some(delivery_seq) = authority.committed_admissions.get(&key) {
            let value = answer(
                request,
                SettlementOutcome::Committed {
                    delivery_seq: *delivery_seq,
                },
            );
            drop(owner);
            return Ok(value);
        }
        if authority
            .committed_admissions
            .range(
                (token, request.participant_id, [0; 32])
                    ..=(token, request.participant_id, [0xff; 32]),
            )
            .next()
            .is_some()
        {
            drop(owner);
            return Ok(RecordAdmissionResponse::attempt_token_body_conflict(
                request.record_admission_attempt_token,
                request.conversation_id,
                request.participant_id,
                request.capability_generation,
            )
            .into_server_value());
        }
        drop(owner);
        Ok(answer(request, SettlementOutcome::NotCommitted))
    }
}