use bytes::Bytes;
use crate::codec::OrderedMap;
use crate::link::settlement::UnsettledMap;
use crate::types::messaging::DeliveryState;
#[derive(Debug, Clone, PartialEq)]
pub enum ResumeAction {
Resend,
Resume,
Settle(DeliveryState),
Abort,
}
pub fn sender_resume_action(local_settled: bool, remote: Option<&DeliveryState>) -> ResumeAction {
match remote {
Some(state) if state.is_terminal() => ResumeAction::Settle(state.clone()),
Some(_) => ResumeAction::Resume,
None if local_settled => ResumeAction::Abort,
None => ResumeAction::Resend,
}
}
pub fn reconcile(
local: &UnsettledMap,
remote: &OrderedMap<Bytes, DeliveryState>,
) -> Vec<(u32, ResumeAction)> {
local
.iter()
.map(|(id, entry)| {
let remote_state = remote.get(&entry.delivery_tag);
(id, sender_resume_action(entry.settled, remote_state))
})
.collect()
}
#[cfg(test)]
mod tests {
use super::*;
use crate::types::messaging::{Accepted, Received, Rejected};
fn accepted() -> DeliveryState {
DeliveryState::Accepted(Accepted::default())
}
fn received() -> DeliveryState {
DeliveryState::Received(Received {
section_number: 0,
section_offset: 0,
})
}
fn rejected() -> DeliveryState {
DeliveryState::Rejected(Rejected { error: None })
}
#[test]
fn sender_matrix() {
assert_eq!(
sender_resume_action(false, Some(&accepted())),
ResumeAction::Settle(accepted())
);
assert_eq!(
sender_resume_action(false, Some(&rejected())),
ResumeAction::Settle(rejected())
);
assert_eq!(
sender_resume_action(false, Some(&received())),
ResumeAction::Resume
);
assert_eq!(sender_resume_action(false, None), ResumeAction::Resend);
assert_eq!(sender_resume_action(true, None), ResumeAction::Abort);
}
#[test]
fn reconcile_over_maps() {
let mut local = UnsettledMap::new();
local.insert(1, Bytes::from_static(b"a"), None); local.insert(2, Bytes::from_static(b"b"), None); local.insert(3, Bytes::from_static(b"c"), None);
let remote = OrderedMap::from(vec![
(Bytes::from_static(b"a"), accepted()),
(Bytes::from_static(b"b"), received()),
]);
let actions = reconcile(&local, &remote);
assert_eq!(
actions,
vec![
(1, ResumeAction::Settle(accepted())),
(2, ResumeAction::Resume),
(3, ResumeAction::Resend),
]
);
}
}