use serde::{Deserialize, Serialize};
use crate::envelope::{CorrelationKind, SlotFill, WireCorrelation, WireEnvelope};
use crate::framework::address_book::Address;
use crate::framework::BackoffCause;
use crate::ids::PeerId;
use crate::slot_value::type_hash_of;
pub const BACKPRESSURE_DOMAIN: &str = "ai.bytesandbrains.backpressure";
#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct BackoffNoticePayload {
pub min_backoff_ns: u64,
pub cause: BackoffCauseWire,
pub suggested_next_send_ns: u64,
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq)]
#[repr(u8)]
pub enum BackoffCauseWire {
QueueFull = 0,
PhiAccrual = 1,
ExplicitDrop = 2,
}
impl From<BackoffCause> for BackoffCauseWire {
fn from(cause: BackoffCause) -> Self {
match cause {
BackoffCause::QueueFull => Self::QueueFull,
BackoffCause::PhiAccrual => Self::PhiAccrual,
BackoffCause::ExplicitDrop => Self::ExplicitDrop,
}
}
}
impl From<BackoffCauseWire> for BackoffCause {
fn from(cause: BackoffCauseWire) -> Self {
match cause {
BackoffCauseWire::QueueFull => Self::QueueFull,
BackoffCauseWire::PhiAccrual => Self::PhiAccrual,
BackoffCauseWire::ExplicitDrop => Self::ExplicitDrop,
}
}
}
impl BackoffNoticePayload {
pub fn new(
min_backoff_ns: u64,
cause: BackoffCause,
suggested_next_send_ns: Option<u64>,
) -> Self {
Self {
min_backoff_ns,
cause: cause.into(),
suggested_next_send_ns: suggested_next_send_ns.unwrap_or(0),
}
}
pub fn suggested_next_send(&self) -> Option<u64> {
if self.suggested_next_send_ns == 0 {
None
} else {
Some(self.suggested_next_send_ns)
}
}
pub fn cause(&self) -> BackoffCause {
self.cause.into()
}
pub fn encode(&self) -> Vec<u8> {
bincode::serialize(self).expect("BackoffNoticePayload bincode serialize is infallible")
}
pub fn decode(bytes: &[u8]) -> Option<Self> {
bincode::deserialize::<Self>(bytes).ok()
}
}
pub fn backoff_notice_type_hash() -> u64 {
type_hash_of::<BackoffNoticePayload>()
}
pub fn build_backoff_notice_envelope(
self_peer: PeerId,
sender: PeerId,
payload: BackoffNoticePayload,
) -> WireEnvelope {
let dest_addr = Address::empty().p2p(sender).to_bytes();
let dest_suffix = Address::empty().p2p(self_peer).to_bytes();
let bytes = payload.encode();
WireEnvelope {
dest_peer_addresses: vec![dest_addr],
fills: vec![SlotFill {
dest_suffix,
payload: bytes,
trigger_only: false,
type_hash: backoff_notice_type_hash(),
}],
correlation: Some(WireCorrelation {
kind: CorrelationKind::None as i32,
wire_req_id: 0,
}),
remaining_deadline_ns: 0,
edge_rtt_reports: Vec::new(),
..Default::default()
}
}