use crate::coordinate::DagPosition;
use crate::event::EventKind;
use crate::id::{CausationId, CorrelationId, EventId};
use serde::{Deserialize, Serialize};
#[repr(C)]
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct EventHeader {
pub event_id: EventId,
pub correlation_id: CorrelationId,
pub causation_id: Option<CausationId>,
pub timestamp_us: i64,
pub position: DagPosition,
pub payload_size: u32,
pub event_kind: EventKind,
pub flags: u8,
#[serde(default)]
pub content_hash: [u8; 32],
}
pub const FLAG_REQUIRES_ACK: u8 = 0x01;
pub const FLAG_TRANSACTIONAL: u8 = 0x02;
pub const FLAG_REPLAY: u8 = 0x08;
impl EventHeader {
pub fn new(
event_id: u128,
correlation_id: u128,
causation_id: Option<u128>,
timestamp_us: i64,
position: DagPosition,
payload_size: u32,
event_kind: EventKind,
) -> Self {
Self {
event_id: EventId::from(event_id),
correlation_id: CorrelationId::from(correlation_id),
causation_id: causation_id.map(CausationId::from),
timestamp_us,
position,
payload_size,
event_kind,
flags: 0,
content_hash: [0u8; 32],
}
}
pub fn new_typed(
event_id: crate::id::EventId,
correlation_id: crate::id::CorrelationId,
causation_id: Option<crate::id::CausationId>,
timestamp_us: i64,
position: DagPosition,
payload_size: u32,
event_kind: EventKind,
) -> Self {
Self {
event_id,
correlation_id,
causation_id,
timestamp_us,
position,
payload_size,
event_kind,
flags: 0,
content_hash: [0u8; 32],
}
}
pub fn with_flags(mut self, flags: u8) -> Self {
self.flags = flags;
self
}
pub fn requires_ack(&self) -> bool {
self.flags & FLAG_REQUIRES_ACK != 0
}
pub fn is_transactional(&self) -> bool {
self.flags & FLAG_TRANSACTIONAL != 0
}
pub fn is_replay(&self) -> bool {
self.flags & FLAG_REPLAY != 0
}
pub fn age_us(&self, now_us: i64) -> u64 {
now_us
.saturating_sub(self.timestamp_us)
.max(0)
.cast_unsigned()
}
}