use crate::book::common::events::{BookEvent, BookEventEnvelope};
use crate::book::common::types::{BookMarketState, BookOrder, CloseProcessState};
use crate::types::{AccountId, OrderId};
pub const MIN_CLOSE_BATCH_EVENTS: u16 = 2;
pub const DEFAULT_CLOSE_BATCH_EVENTS: u16 = 4096;
pub fn close_start_reason(batch_max_events: u16) -> String {
format!("CLOSE_START:{batch_max_events}")
}
pub fn parse_close_start_batch_max_events(reason: &str) -> Option<u16> {
reason
.strip_prefix("CLOSE_START:")
.and_then(|s| s.parse::<u16>().ok())
}
#[inline]
pub fn is_live_order(o: &BookOrder) -> bool {
matches!(
o.info.state,
crate::book::common::types::BookOrderState::ExecutableUnmatched
| crate::book::common::types::BookOrderState::ExecutablePartiallyMatched
)
}
pub fn count_live_orders<'a>(orders: impl Iterator<Item = (OrderId, &'a BookOrder)>) -> u64 {
orders.filter(|(_, o)| is_live_order(o)).count() as u64
}
pub fn close_start_batch(
batch_max_events: u16,
mut state_change: impl FnMut(BookMarketState, &str, &mut Vec<BookEventEnvelope>),
emit: impl Fn(BookEvent) -> BookEventEnvelope,
mut cancel_chunk: impl FnMut(
Option<OrderId>,
usize,
) -> (
Vec<OrderId>,
Vec<AccountId>,
Option<OrderId>,
Option<AccountId>,
bool,
u64,
),
) -> Vec<BookEventEnvelope> {
let cancel_budget = batch_max_events as usize;
let (cancelled_order_ids, account_ids, cursor_after, cursor_after_account_id, done, _) =
cancel_chunk(None, cancel_budget);
let mut events = Vec::new();
let reason = close_start_reason(batch_max_events);
state_change(BookMarketState::Closed, &reason, &mut events);
events.push(emit(BookEvent::OrderCancelled {
cursor_after: if done { None } else { cursor_after },
cursor_after_account_id: if done { None } else { cursor_after_account_id },
order_ids: cancelled_order_ids,
account_ids,
is_final: done,
cancel_cause: crate::book::common::events::CancelCause::CloseCancel,
cause_detail: None,
}));
events
}
pub fn close_continue_batch(
proc_state: CloseProcessState,
state_change: impl FnMut(BookMarketState, &str, &mut Vec<BookEventEnvelope>),
emit: impl Fn(BookEvent) -> BookEventEnvelope,
mut cancel_chunk: impl FnMut(
Option<OrderId>,
usize,
) -> (
Vec<OrderId>,
Vec<AccountId>,
Option<OrderId>,
Option<AccountId>,
bool,
u64,
),
) -> Vec<BookEventEnvelope> {
let mut events = Vec::new();
let cancel_budget = proc_state.batch_max_events as usize; let (cancelled_order_ids, account_ids, cursor_after, cursor_after_account_id, done, _) =
cancel_chunk(proc_state.cursor_after, cancel_budget);
let _ = state_change;
events.push(emit(BookEvent::OrderCancelled {
cursor_after: if done { None } else { cursor_after },
cursor_after_account_id: if done { None } else { cursor_after_account_id },
order_ids: cancelled_order_ids,
account_ids,
is_final: done,
cancel_cause: crate::book::common::events::CancelCause::CloseCancel,
cause_detail: None,
}));
events
}