liminal-server 0.25.4

Standalone server for the liminal messaging bus
Documentation
//! A far call's answer is released whatever became of its execution's
//! retirement: a retirement that fails is logged, never a reason to withhold
//! the answer or to end the link that carried the call.
use super::{Completion, Pending, answered};
use crate::link::calls::{CallError, CallExecution, CallReply};
use liminal::protocol::Frame;

type TestResult = Result<(), Box<dyn std::error::Error>>;

#[derive(Debug)]
struct Unretirable;
impl CallExecution for Unretirable {
    fn finish(&mut self) -> Result<(), CallError> {
        Err(CallError::Unavailable)
    }
}

fn refusal(code: u16) -> Frame {
    Frame::ConversationError {
        flags: 0,
        stream_id: 2,
        conversation_id: 1,
        reason_code: code,
        message: None,
    }
}

#[test]
fn a_retirement_that_fails_never_withholds_the_answer_in_hand() -> TestResult {
    let mut pending = Pending {
        subject: "embed.bge".to_owned(),
        correlation: (2, 1),
        execution: Box::new(Unretirable),
    };
    let completion = Completion {
        id: 7,
        subject: "embed.bge".to_owned(),
        answer: Ok(CallReply::new(7, refusal(42))?),
    };
    let reply = answered(&mut pending, completion, |_| Ok(()))
        .map_err(|error| format!("the answer in hand was withheld: {error}"))?;
    assert_eq!(reply.id(), 7);
    assert!(matches!(
        reply.into_frame(),
        Frame::ConversationError {
            reason_code: 42,
            ..
        }
    ));
    Ok(())
}

#[test]
fn a_subject_that_differs_from_the_call_is_a_correlation_refusal() -> TestResult {
    let mut pending = Pending {
        subject: "embed.bge".to_owned(),
        correlation: (2, 1),
        execution: Box::new(Unretirable),
    };
    let completion = Completion {
        id: 7,
        subject: "embed.other".to_owned(),
        answer: Ok(CallReply::new(7, refusal(1))?),
    };
    assert_eq!(
        answered(&mut pending, completion, |_| Ok(())).err(),
        Some(CallError::Correlation)
    );
    Ok(())
}