use freenet_stdlib::prelude::*;
use serde::{Deserialize, Serialize};
use crate::{
message::Transaction,
node::PeerId,
ring::{Location, PeerKeyLocation},
router::RouteEvent,
};
#[derive(Serialize, Deserialize, Debug, Clone)]
#[cfg_attr(test, derive(arbitrary::Arbitrary))]
#[non_exhaustive]
#[allow(private_interfaces)]
pub enum EventKind {
Connect(ConnectEvent),
Put(PutEvent),
Get(GetEvent),
Subscribe(SubscribeEvent),
Route(RouteEvent),
Update(UpdateEvent),
Transfer(TransferEvent),
Lifecycle(PeerLifecycleEvent),
Ignored,
Disconnected {
from: PeerId,
reason: DisconnectReason,
connection_duration_ms: Option<u64>,
bytes_sent: Option<u64>,
bytes_received: Option<u64>,
},
Timeout {
id: Transaction,
timestamp: u64,
op_type: String,
target_peer: Option<String>,
},
TransportSnapshot(crate::transport::TransportSnapshot),
InterestSync(InterestSyncEvent),
RoutingDecision(crate::router::RoutingDecisionInfo),
RouterSnapshot(Box<crate::router::RouterSnapshotInfo>),
}
impl EventKind {
pub(crate) const CONNECT: u8 = 0;
pub(crate) const PUT: u8 = 1;
pub(crate) const GET: u8 = 2;
pub(crate) const ROUTE: u8 = 3;
pub(crate) const SUBSCRIBE: u8 = 4;
pub(crate) const IGNORED: u8 = 5;
pub(crate) const DISCONNECTED: u8 = 6;
pub(crate) const UPDATE: u8 = 7;
pub(crate) const TIMEOUT: u8 = 8;
pub(crate) const TRANSFER: u8 = 9;
pub(crate) const LIFECYCLE: u8 = 10;
pub(crate) const TRANSPORT_SNAPSHOT: u8 = 11;
pub(crate) const INTEREST_SYNC: u8 = 12;
pub(crate) const ROUTING_DECISION: u8 = 13;
pub(crate) const ROUTER_SNAPSHOT: u8 = 14;
pub(crate) const fn varint_id(&self) -> u8 {
match self {
EventKind::Connect(_) => Self::CONNECT,
EventKind::Put(_) => Self::PUT,
EventKind::Get(_) => Self::GET,
EventKind::Route(_) => Self::ROUTE,
EventKind::Subscribe(_) => Self::SUBSCRIBE,
EventKind::Ignored => Self::IGNORED,
EventKind::Disconnected { .. } => Self::DISCONNECTED,
EventKind::Update(_) => Self::UPDATE,
EventKind::Timeout { .. } => Self::TIMEOUT,
EventKind::Transfer(_) => Self::TRANSFER,
EventKind::Lifecycle(_) => Self::LIFECYCLE,
EventKind::TransportSnapshot(_) => Self::TRANSPORT_SNAPSHOT,
EventKind::InterestSync(_) => Self::INTEREST_SYNC,
EventKind::RoutingDecision(_) => Self::ROUTING_DECISION,
EventKind::RouterSnapshot(_) => Self::ROUTER_SNAPSHOT,
}
}
pub fn contract_key(&self) -> Option<freenet_stdlib::prelude::ContractKey> {
match self {
EventKind::Put(put) => Some(put.contract_key()),
EventKind::Get(get) => get.contract_key(),
EventKind::Subscribe(sub) => sub.contract_key(),
EventKind::Update(upd) => Some(upd.contract_key()),
EventKind::Connect(_)
| EventKind::Route(_)
| EventKind::Transfer(_)
| EventKind::Lifecycle(_)
| EventKind::Ignored
| EventKind::Disconnected { .. }
| EventKind::Timeout { .. }
| EventKind::TransportSnapshot(_)
| EventKind::RoutingDecision(_)
| EventKind::RouterSnapshot(_) => None,
EventKind::InterestSync(InterestSyncEvent::StateConfirmed { key, .. }) => Some(*key),
EventKind::InterestSync(_) => None,
}
}
pub fn state_hash(&self) -> Option<&str> {
match self {
EventKind::Put(put) => put.state_hash(),
EventKind::Update(upd) => upd.state_hash(),
EventKind::Connect(_)
| EventKind::Get(_)
| EventKind::Subscribe(_)
| EventKind::Route(_)
| EventKind::Transfer(_)
| EventKind::Lifecycle(_)
| EventKind::Ignored
| EventKind::Disconnected { .. }
| EventKind::Timeout { .. }
| EventKind::TransportSnapshot(_)
| EventKind::InterestSync(_)
| EventKind::RoutingDecision(_)
| EventKind::RouterSnapshot(_) => None,
}
}
pub fn stored_state_hash(&self) -> Option<&str> {
match self {
EventKind::Put(put) => put.stored_state_hash(),
EventKind::Update(upd) => upd.stored_state_hash(),
EventKind::Connect(_)
| EventKind::Get(_)
| EventKind::Subscribe(_)
| EventKind::Route(_)
| EventKind::Transfer(_)
| EventKind::Lifecycle(_)
| EventKind::Ignored
| EventKind::Disconnected { .. }
| EventKind::Timeout { .. }
| EventKind::TransportSnapshot(_)
| EventKind::RoutingDecision(_)
| EventKind::RouterSnapshot(_) => None,
EventKind::InterestSync(InterestSyncEvent::StateConfirmed { state_hash, .. }) => {
Some(state_hash.as_str())
}
EventKind::InterestSync(_) => None,
}
}
pub fn is_update_broadcast_emitted(&self) -> bool {
matches!(
self,
EventKind::Update(UpdateEvent::BroadcastEmitted { .. })
)
}
pub fn router_snapshot_summary(&self) -> Option<(usize, usize, bool)> {
match self {
EventKind::RouterSnapshot(info) => Some((
info.failure_events,
info.success_events,
info.prediction_active,
)),
EventKind::Connect(_)
| EventKind::Put(_)
| EventKind::Get(_)
| EventKind::Subscribe(_)
| EventKind::Route(_)
| EventKind::Update(_)
| EventKind::Transfer(_)
| EventKind::Lifecycle(_)
| EventKind::Ignored
| EventKind::Disconnected { .. }
| EventKind::Timeout { .. }
| EventKind::TransportSnapshot(_)
| EventKind::InterestSync(_)
| EventKind::RoutingDecision(_) => None,
}
}
pub fn route_outcome_is_success(&self) -> Option<bool> {
match self {
EventKind::Route(re) => Some(match re.outcome {
crate::router::RouteOutcome::Success { .. }
| crate::router::RouteOutcome::SuccessUntimed => true,
crate::router::RouteOutcome::Failure => false,
}),
EventKind::Connect(_)
| EventKind::Put(_)
| EventKind::Get(_)
| EventKind::Subscribe(_)
| EventKind::Update(_)
| EventKind::Transfer(_)
| EventKind::Lifecycle(_)
| EventKind::Ignored
| EventKind::Disconnected { .. }
| EventKind::Timeout { .. }
| EventKind::TransportSnapshot(_)
| EventKind::InterestSync(_)
| EventKind::RoutingDecision(_)
| EventKind::RouterSnapshot(_) => None,
}
}
pub fn get_outcome(&self) -> Option<bool> {
match self {
EventKind::Get(GetEvent::GetSuccess { .. }) => Some(true),
EventKind::Get(GetEvent::GetNotFound { .. } | GetEvent::GetFailure { .. }) => {
Some(false)
}
EventKind::Connect(_)
| EventKind::Put(_)
| EventKind::Get(_)
| EventKind::Subscribe(_)
| EventKind::Route(_)
| EventKind::Update(_)
| EventKind::Transfer(_)
| EventKind::Lifecycle(_)
| EventKind::Ignored
| EventKind::Disconnected { .. }
| EventKind::Timeout { .. }
| EventKind::TransportSnapshot(_)
| EventKind::InterestSync(_)
| EventKind::RoutingDecision(_)
| EventKind::RouterSnapshot(_) => None,
}
}
pub fn get_elapsed_ms(&self) -> Option<u64> {
match self {
EventKind::Get(GetEvent::GetSuccess { elapsed_ms, .. })
| EventKind::Get(GetEvent::GetNotFound { elapsed_ms, .. })
| EventKind::Get(GetEvent::GetFailure { elapsed_ms, .. }) => Some(*elapsed_ms),
EventKind::Connect(_)
| EventKind::Put(_)
| EventKind::Get(_)
| EventKind::Subscribe(_)
| EventKind::Route(_)
| EventKind::Update(_)
| EventKind::Transfer(_)
| EventKind::Lifecycle(_)
| EventKind::Ignored
| EventKind::Disconnected { .. }
| EventKind::Timeout { .. }
| EventKind::TransportSnapshot(_)
| EventKind::InterestSync(_)
| EventKind::RoutingDecision(_)
| EventKind::RouterSnapshot(_) => None,
}
}
pub fn is_forwarding_ack_received(&self) -> bool {
matches!(self, EventKind::Get(GetEvent::ForwardingAckReceived { .. }))
}
pub fn is_get_response_sent(&self) -> bool {
matches!(self, EventKind::Get(GetEvent::ResponseSent { .. }))
}
pub fn is_get_request(&self) -> bool {
matches!(self, EventKind::Get(GetEvent::Request { .. }))
}
#[allow(clippy::wildcard_enum_match_arm)]
pub fn get_request_htl(&self) -> Option<usize> {
match self {
EventKind::Get(GetEvent::Request { htl, .. }) => Some(*htl),
_ => None,
}
}
pub fn subscribe_outcome(&self) -> Option<bool> {
match self {
EventKind::Subscribe(SubscribeEvent::SubscribeSuccess { .. }) => Some(true),
EventKind::Subscribe(SubscribeEvent::SubscribeNotFound { .. })
| EventKind::Subscribe(SubscribeEvent::SubscribeTimeout { .. }) => Some(false),
EventKind::Connect(_)
| EventKind::Put(_)
| EventKind::Get(_)
| EventKind::Subscribe(_)
| EventKind::Route(_)
| EventKind::Update(_)
| EventKind::Transfer(_)
| EventKind::Lifecycle(_)
| EventKind::Ignored
| EventKind::Disconnected { .. }
| EventKind::Timeout { .. }
| EventKind::TransportSnapshot(_)
| EventKind::InterestSync(_)
| EventKind::RoutingDecision(_)
| EventKind::RouterSnapshot(_) => None,
}
}
pub fn is_update_broadcast_received(&self) -> bool {
matches!(
self,
EventKind::Update(UpdateEvent::BroadcastReceived { .. })
)
}
pub fn is_connect(&self) -> bool {
matches!(self, EventKind::Connect(_))
}
pub fn is_disconnected(&self) -> bool {
matches!(self, EventKind::Disconnected { .. })
}
pub fn is_connect_accepted(&self) -> bool {
matches!(
self,
EventKind::Connect(ConnectEvent::RequestReceived { accepted: true, .. })
)
}
pub fn is_connect_not_accepted(&self) -> bool {
matches!(
self,
EventKind::Connect(ConnectEvent::RequestReceived {
accepted: false,
..
})
)
}
pub fn is_connect_connected(&self) -> bool {
matches!(self, EventKind::Connect(ConnectEvent::Connected { .. }))
}
pub fn is_connect_initiated(&self) -> bool {
matches!(
self,
EventKind::Connect(ConnectEvent::RequestSent {
is_initial: true,
..
})
)
}
pub fn is_connect_terminus_accepted(&self) -> bool {
matches!(
self,
EventKind::Connect(ConnectEvent::RequestReceived {
accepted: true,
forwarded_to: None,
..
})
)
}
pub fn is_connect_terminus_rejected(&self) -> bool {
matches!(
self,
EventKind::Connect(ConnectEvent::RequestReceived {
accepted: false,
forwarded_to: None,
..
})
)
}
pub fn is_connect_forwarded(&self) -> bool {
matches!(
self,
EventKind::Connect(ConnectEvent::RequestReceived {
forwarded_to: Some(_),
..
})
)
}
#[allow(clippy::wildcard_enum_match_arm)]
pub fn connect_peer_connection_count(&self) -> Option<usize> {
match self {
EventKind::Connect(ConnectEvent::Connected {
this_peer_connection_count,
..
}) => Some(*this_peer_connection_count),
_ => None,
}
}
#[allow(clippy::wildcard_enum_match_arm)]
pub fn unsubscribe_received_instance_id(&self) -> Option<&ContractInstanceId> {
match self {
EventKind::Subscribe(SubscribeEvent::UnsubscribeReceived { instance_id, .. }) => {
Some(instance_id)
}
_ => None,
}
}
#[allow(clippy::wildcard_enum_match_arm)]
pub fn unsubscribe_sent_instance_id(&self) -> Option<&ContractInstanceId> {
match self {
EventKind::Subscribe(SubscribeEvent::UnsubscribeSent { instance_id, .. }) => {
Some(instance_id)
}
_ => None,
}
}
#[allow(clippy::wildcard_enum_match_arm)]
pub fn hop_count(&self) -> Option<usize> {
match self {
EventKind::Get(GetEvent::GetSuccess { hop_count, .. })
| EventKind::Get(GetEvent::GetNotFound { hop_count, .. })
| EventKind::Get(GetEvent::GetFailure { hop_count, .. })
| EventKind::Put(PutEvent::PutSuccess { hop_count, .. })
| EventKind::Subscribe(SubscribeEvent::SubscribeSuccess { hop_count, .. })
| EventKind::Subscribe(SubscribeEvent::SubscribeNotFound { hop_count, .. }) => {
*hop_count
}
_ => None,
}
}
pub fn variant_name(&self) -> &'static str {
match self {
EventKind::Connect(_) => "Connect",
EventKind::Put(_) => "Put",
EventKind::Get(_) => "Get",
EventKind::Subscribe(_) => "Subscribe",
EventKind::Route(_) => "Route",
EventKind::Update(_) => "Update",
EventKind::Transfer(_) => "Transfer",
EventKind::Lifecycle(_) => "Lifecycle",
EventKind::Ignored => "Ignored",
EventKind::Disconnected { .. } => "Disconnected",
EventKind::Timeout { .. } => "Timeout",
EventKind::TransportSnapshot(_) => "TransportSnapshot",
EventKind::InterestSync(_) => "InterestSync",
EventKind::RoutingDecision(_) => "RoutingDecision",
EventKind::RouterSnapshot(_) => "RouterSnapshot",
}
}
}
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Default)]
#[cfg_attr(test, derive(arbitrary::Arbitrary))]
pub enum ConnectionType {
Direct,
Relayed,
Gateway,
#[default]
Unknown,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Default)]
#[cfg_attr(test, derive(arbitrary::Arbitrary))]
pub enum DisconnectReason {
Explicit(String),
Pruned,
Timeout,
NetworkError(String),
Unresponsive,
RemoteDropped,
ConnectionLimitReached,
#[default]
Unknown,
}
impl From<Option<String>> for DisconnectReason {
fn from(reason: Option<String>) -> Self {
match reason {
Some(s) if s.contains("pruned") => DisconnectReason::Pruned,
Some(s) if s.contains("timeout") => DisconnectReason::Timeout,
Some(s) if s.contains("unresponsive") => DisconnectReason::Unresponsive,
Some(s) if s.contains("limit") => DisconnectReason::ConnectionLimitReached,
Some(s) => DisconnectReason::Explicit(s),
None => DisconnectReason::Unknown,
}
}
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[cfg_attr(test, derive(arbitrary::Arbitrary))]
#[allow(clippy::large_enum_variant)] pub(crate) enum ConnectEvent {
StartConnection {
from: PeerId,
is_gateway: bool,
},
Connected {
this: PeerKeyLocation,
connected: PeerKeyLocation,
elapsed_ms: Option<u64>,
connection_type: ConnectionType,
latency_ms: Option<u64>,
this_peer_connection_count: usize,
initiated_by: Option<PeerId>,
},
Finished {
initiator: PeerId,
location: Location,
elapsed_ms: Option<u64>,
},
RequestSent {
desired_location: Location,
joiner: PeerKeyLocation,
target: PeerKeyLocation,
ttl: u8,
is_initial: bool,
},
RequestReceived {
desired_location: Location,
joiner: PeerKeyLocation,
from_addr: std::net::SocketAddr,
from_peer: Option<PeerKeyLocation>,
forwarded_to: Option<PeerKeyLocation>,
accepted: bool,
ttl: u8,
},
ResponseSent {
acceptor: PeerKeyLocation,
joiner: PeerKeyLocation,
},
ResponseReceived {
acceptor: PeerKeyLocation,
elapsed_ms: u64,
},
Rejected {
desired_location: Location,
reason: String,
},
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
#[cfg_attr(test, derive(arbitrary::Arbitrary))]
pub enum OperationFailure {
ConnectionDropped,
MaxRetriesExceeded { retries: usize },
HtlExhausted,
NoPeersAvailable,
ContractError(String),
Timeout,
Other(String),
}
impl std::fmt::Display for ConnectionType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ConnectionType::Direct => write!(f, "direct"),
ConnectionType::Relayed => write!(f, "relayed"),
ConnectionType::Gateway => write!(f, "gateway"),
ConnectionType::Unknown => write!(f, "unknown"),
}
}
}
impl std::fmt::Display for DisconnectReason {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
DisconnectReason::Explicit(reason) => write!(f, "explicit: {}", reason),
DisconnectReason::Pruned => write!(f, "pruned"),
DisconnectReason::Timeout => write!(f, "timeout"),
DisconnectReason::NetworkError(err) => write!(f, "network_error: {}", err),
DisconnectReason::Unresponsive => write!(f, "unresponsive"),
DisconnectReason::RemoteDropped => write!(f, "remote_dropped"),
DisconnectReason::ConnectionLimitReached => write!(f, "connection_limit_reached"),
DisconnectReason::Unknown => write!(f, "unknown"),
}
}
}
impl std::fmt::Display for OperationFailure {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
OperationFailure::ConnectionDropped => write!(f, "connection_dropped"),
OperationFailure::MaxRetriesExceeded { retries } => {
write!(f, "max_retries_exceeded: {}", retries)
}
OperationFailure::HtlExhausted => write!(f, "htl_exhausted"),
OperationFailure::NoPeersAvailable => write!(f, "no_peers_available"),
OperationFailure::ContractError(err) => write!(f, "contract_error: {}", err),
OperationFailure::Timeout => write!(f, "timeout"),
OperationFailure::Other(reason) => write!(f, "other: {}", reason),
}
}
}
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
#[cfg_attr(test, derive(arbitrary::Arbitrary))]
pub(crate) enum PutEvent {
Request {
id: Transaction,
requester: PeerKeyLocation,
key: ContractKey,
target: PeerKeyLocation,
htl: usize,
timestamp: u64,
},
PutSuccess {
id: Transaction,
requester: PeerKeyLocation,
target: PeerKeyLocation,
key: ContractKey,
hop_count: Option<usize>,
elapsed_ms: u64,
timestamp: u64,
state_hash: Option<String>,
state_size: Option<usize>,
},
PutFailure {
id: Transaction,
requester: PeerKeyLocation,
target: PeerKeyLocation,
key: ContractKey,
hop_count: Option<usize>,
reason: OperationFailure,
elapsed_ms: u64,
timestamp: u64,
},
ResponseSent {
id: Transaction,
from: PeerKeyLocation,
to: PeerKeyLocation,
key: ContractKey,
timestamp: u64,
},
BroadcastEmitted {
id: Transaction,
upstream: PeerKeyLocation,
broadcast_to: Vec<PeerKeyLocation>,
broadcasted_to: usize,
key: ContractKey,
value: WrappedState,
sender: PeerKeyLocation,
timestamp: u64,
state_hash: Option<String>,
},
BroadcastReceived {
id: Transaction,
requester: PeerKeyLocation,
key: ContractKey,
value: WrappedState,
target: PeerKeyLocation,
timestamp: u64,
state_hash: Option<String>,
},
}
impl PutEvent {
fn contract_key(&self) -> ContractKey {
match self {
PutEvent::Request { key, .. }
| PutEvent::PutSuccess { key, .. }
| PutEvent::PutFailure { key, .. }
| PutEvent::ResponseSent { key, .. }
| PutEvent::BroadcastEmitted { key, .. }
| PutEvent::BroadcastReceived { key, .. } => *key,
}
}
fn state_hash(&self) -> Option<&str> {
match self {
PutEvent::PutSuccess { state_hash, .. }
| PutEvent::BroadcastEmitted { state_hash, .. }
| PutEvent::BroadcastReceived { state_hash, .. } => state_hash.as_deref(),
PutEvent::Request { .. }
| PutEvent::PutFailure { .. }
| PutEvent::ResponseSent { .. } => None,
}
}
fn stored_state_hash(&self) -> Option<&str> {
match self {
PutEvent::PutSuccess { state_hash, .. } => state_hash.as_deref(),
PutEvent::Request { .. }
| PutEvent::PutFailure { .. }
| PutEvent::ResponseSent { .. }
| PutEvent::BroadcastEmitted { .. }
| PutEvent::BroadcastReceived { .. } => None,
}
}
}
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
#[cfg_attr(test, derive(arbitrary::Arbitrary))]
pub(crate) enum UpdateEvent {
Request {
id: Transaction,
requester: PeerKeyLocation,
key: ContractKey,
target: PeerKeyLocation,
timestamp: u64,
},
UpdateSuccess {
id: Transaction,
requester: PeerKeyLocation,
target: PeerKeyLocation,
key: ContractKey,
timestamp: u64,
state_hash_before: Option<String>,
state_hash_after: Option<String>,
state_size: Option<usize>,
},
BroadcastEmitted {
id: Transaction,
upstream: PeerKeyLocation,
broadcast_to: Vec<PeerKeyLocation>,
broadcasted_to: usize,
key: ContractKey,
value: WrappedState,
sender: PeerKeyLocation,
timestamp: u64,
state_hash: Option<String>,
},
UpdateFailure {
id: Transaction,
requester: PeerKeyLocation,
target: PeerKeyLocation,
key: ContractKey,
reason: OperationFailure,
elapsed_ms: u64,
timestamp: u64,
},
BroadcastComplete {
id: Transaction,
key: ContractKey,
delta_sends: usize,
full_state_sends: usize,
bytes_saved: u64,
state_size: usize,
timestamp: u64,
},
BroadcastReceived {
id: Transaction,
requester: PeerKeyLocation,
key: ContractKey,
value: WrappedState,
target: PeerKeyLocation,
timestamp: u64,
state_hash: Option<String>,
},
BroadcastApplied {
id: Transaction,
key: ContractKey,
target: PeerKeyLocation,
timestamp: u64,
state_hash_before: Option<String>,
state_hash_after: Option<String>,
changed: bool,
state_size: usize,
},
BroadcastDeliverySummary {
key: ContractKey,
proximity_found: usize,
proximity_resolve_failed: usize,
interest_found: usize,
interest_resolve_failed: usize,
skipped_self: usize,
skipped_sender: usize,
skipped_summary_match: usize,
targets_sent: usize,
send_failed: usize,
timestamp: u64,
},
}
impl UpdateEvent {
fn contract_key(&self) -> ContractKey {
match self {
UpdateEvent::Request { key, .. }
| UpdateEvent::UpdateSuccess { key, .. }
| UpdateEvent::BroadcastEmitted { key, .. }
| UpdateEvent::BroadcastComplete { key, .. }
| UpdateEvent::BroadcastReceived { key, .. }
| UpdateEvent::BroadcastApplied { key, .. }
| UpdateEvent::UpdateFailure { key, .. }
| UpdateEvent::BroadcastDeliverySummary { key, .. } => *key,
}
}
fn state_hash(&self) -> Option<&str> {
match self {
UpdateEvent::UpdateSuccess {
state_hash_after, ..
}
| UpdateEvent::BroadcastApplied {
state_hash_after, ..
} => state_hash_after.as_deref(),
UpdateEvent::BroadcastEmitted { state_hash, .. }
| UpdateEvent::BroadcastReceived { state_hash, .. } => state_hash.as_deref(),
UpdateEvent::Request { .. }
| UpdateEvent::UpdateFailure { .. }
| UpdateEvent::BroadcastComplete { .. }
| UpdateEvent::BroadcastDeliverySummary { .. } => None,
}
}
fn stored_state_hash(&self) -> Option<&str> {
match self {
UpdateEvent::UpdateSuccess {
state_hash_after, ..
}
| UpdateEvent::BroadcastApplied {
state_hash_after, ..
} => state_hash_after.as_deref(),
UpdateEvent::Request { .. }
| UpdateEvent::UpdateFailure { .. }
| UpdateEvent::BroadcastEmitted { .. }
| UpdateEvent::BroadcastComplete { .. }
| UpdateEvent::BroadcastReceived { .. }
| UpdateEvent::BroadcastDeliverySummary { .. } => None,
}
}
}
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
#[cfg_attr(test, derive(arbitrary::Arbitrary))]
pub(crate) enum GetEvent {
Request {
id: Transaction,
requester: PeerKeyLocation,
instance_id: ContractInstanceId,
target: PeerKeyLocation,
htl: usize,
timestamp: u64,
},
GetSuccess {
id: Transaction,
requester: PeerKeyLocation,
target: PeerKeyLocation,
key: ContractKey,
hop_count: Option<usize>,
elapsed_ms: u64,
timestamp: u64,
state_hash: Option<String>,
},
GetNotFound {
id: Transaction,
requester: PeerKeyLocation,
instance_id: ContractInstanceId,
target: PeerKeyLocation,
hop_count: Option<usize>,
elapsed_ms: u64,
timestamp: u64,
},
GetFailure {
id: Transaction,
requester: PeerKeyLocation,
instance_id: ContractInstanceId,
target: PeerKeyLocation,
hop_count: Option<usize>,
reason: OperationFailure,
elapsed_ms: u64,
timestamp: u64,
},
ResponseSent {
id: Transaction,
from: PeerKeyLocation,
to: PeerKeyLocation,
key: Option<ContractKey>,
timestamp: u64,
},
ForwardingAckSent {
id: Transaction,
from: PeerKeyLocation,
to: PeerKeyLocation,
instance_id: ContractInstanceId,
timestamp: u64,
},
ForwardingAckReceived {
id: Transaction,
receiver: PeerKeyLocation,
instance_id: ContractInstanceId,
elapsed_ms: u64,
timestamp: u64,
},
}
impl GetEvent {
fn contract_key(&self) -> Option<ContractKey> {
match self {
GetEvent::GetSuccess { key, .. } => Some(*key),
GetEvent::ResponseSent { key, .. } => *key,
GetEvent::Request { .. }
| GetEvent::GetNotFound { .. }
| GetEvent::GetFailure { .. }
| GetEvent::ForwardingAckSent { .. }
| GetEvent::ForwardingAckReceived { .. } => None,
}
}
}
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
#[cfg_attr(test, derive(arbitrary::Arbitrary))]
pub(crate) enum SubscribeEvent {
Request {
id: Transaction,
requester: PeerKeyLocation,
instance_id: ContractInstanceId,
target: PeerKeyLocation,
htl: usize,
timestamp: u64,
},
SubscribeSuccess {
id: Transaction,
key: ContractKey,
at: PeerKeyLocation,
hop_count: Option<usize>,
elapsed_ms: u64,
timestamp: u64,
requester: PeerKeyLocation,
},
SubscribeNotFound {
id: Transaction,
requester: PeerKeyLocation,
instance_id: ContractInstanceId,
target: PeerKeyLocation,
hop_count: Option<usize>,
elapsed_ms: u64,
timestamp: u64,
},
ResponseSent {
id: Transaction,
from: PeerKeyLocation,
to: PeerKeyLocation,
key: Option<ContractKey>,
timestamp: u64,
},
HostingStarted {
instance_id: ContractInstanceId,
timestamp: u64,
},
HostingStopped {
instance_id: ContractInstanceId,
reason: HostingStoppedReason,
timestamp: u64,
},
#[doc(hidden)]
_Reserved6,
#[doc(hidden)]
_Reserved7,
#[doc(hidden)]
_Reserved8,
#[doc(hidden)]
_Reserved9,
#[doc(hidden)]
_Reserved10,
UnsubscribeSent {
id: Transaction,
instance_id: ContractInstanceId,
from: PeerKeyLocation,
to: PeerKeyLocation,
timestamp: u64,
},
UnsubscribeReceived {
id: Transaction,
instance_id: ContractInstanceId,
from: PeerKeyLocation,
at: PeerKeyLocation,
timestamp: u64,
},
SubscribeTimeout {
id: Transaction,
requester: PeerKeyLocation,
instance_id: ContractInstanceId,
retries: usize,
elapsed_ms: u64,
timestamp: u64,
},
}
impl SubscribeEvent {
fn contract_key(&self) -> Option<ContractKey> {
match self {
SubscribeEvent::SubscribeSuccess { key, .. } => Some(*key),
SubscribeEvent::ResponseSent { key, .. } => *key,
SubscribeEvent::Request { .. }
| SubscribeEvent::SubscribeNotFound { .. }
| SubscribeEvent::HostingStarted { .. }
| SubscribeEvent::HostingStopped { .. }
| SubscribeEvent::_Reserved6
| SubscribeEvent::_Reserved7
| SubscribeEvent::_Reserved8
| SubscribeEvent::_Reserved9
| SubscribeEvent::_Reserved10
| SubscribeEvent::UnsubscribeSent { .. }
| SubscribeEvent::UnsubscribeReceived { .. }
| SubscribeEvent::SubscribeTimeout { .. } => None,
}
}
}
#[derive(Debug, PartialEq, Eq, Clone, Copy, Serialize, Deserialize)]
#[cfg_attr(test, derive(arbitrary::Arbitrary))]
pub enum HostingStoppedReason {
LastClientUnsubscribed,
ClientDisconnected,
}
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(test, derive(arbitrary::Arbitrary))]
pub enum TransferDirection {
Send,
Receive,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[cfg_attr(test, derive(arbitrary::Arbitrary))]
pub enum TransferEvent {
Started {
stream_id: u64,
peer_addr: std::net::SocketAddr,
expected_bytes: u64,
direction: TransferDirection,
tx_id: Option<Transaction>,
timestamp: u64,
},
Completed {
stream_id: u64,
peer_addr: std::net::SocketAddr,
bytes_transferred: u64,
elapsed_ms: u64,
avg_throughput_bps: u64,
peak_cwnd_bytes: Option<u32>,
final_cwnd_bytes: Option<u32>,
slowdowns_triggered: Option<u32>,
final_srtt_ms: Option<u32>,
final_ssthresh_bytes: Option<u32>,
min_ssthresh_floor_bytes: Option<u32>,
total_timeouts: Option<u32>,
direction: TransferDirection,
timestamp: u64,
},
Failed {
stream_id: u64,
peer_addr: std::net::SocketAddr,
bytes_transferred: u64,
reason: String,
elapsed_ms: u64,
direction: TransferDirection,
timestamp: u64,
},
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[cfg_attr(test, derive(arbitrary::Arbitrary))]
pub enum PeerLifecycleEvent {
Startup {
version: String,
git_commit: Option<String>,
git_dirty: Option<bool>,
arch: String,
os: String,
os_version: Option<String>,
is_gateway: bool,
timestamp: u64,
},
Shutdown {
graceful: bool,
reason: Option<String>,
uptime_secs: u64,
total_connections: u64,
timestamp: u64,
},
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[cfg_attr(test, derive(arbitrary::Arbitrary))]
pub enum InterestSyncEvent {
ResyncRequestReceived {
key: ContractKey,
from_peer: PeerKeyLocation,
timestamp: u64,
},
ResyncResponseSent {
key: ContractKey,
to_peer: PeerKeyLocation,
state_size: usize,
timestamp: u64,
},
StateConfirmed {
key: ContractKey,
state_hash: String,
},
}