1use crate::subscription::SubKind;
2use barter_instrument::{exchange::ExchangeId, index::error::IndexError};
3use barter_integration::{error::SocketError, subscription::SubscriptionId};
4use serde::{Deserialize, Serialize};
5use thiserror::Error;
6
7#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize, Error)]
9pub enum DataError {
10 #[error("failed to index market data Subscriptions: {0}")]
11 Index(#[from] IndexError),
12
13 #[error("failed to initialise reconnecting MarketStream due to empty subscriptions")]
14 SubscriptionsEmpty,
15
16 #[error("unsupported DynamicStreams Subscription SubKind: {0}")]
17 UnsupportedSubKind(SubKind),
18
19 #[error("initial snapshot missing for: {0}")]
20 InitialSnapshotMissing(SubscriptionId),
21
22 #[error("initial snapshot invalid: {0}")]
23 InitialSnapshotInvalid(String),
24
25 #[error("SocketError: {0}")]
26 Socket(String),
27
28 #[error("unsupported dynamic Subscription for exchange: {exchange}, kind: {sub_kind}")]
29 Unsupported {
30 exchange: ExchangeId,
31 sub_kind: SubKind,
32 },
33
34 #[error(
35 "\
36 InvalidSequence: first_update_id {first_update_id} does not follow on from the \
37 prev_last_update_id {prev_last_update_id} \
38 "
39 )]
40 InvalidSequence {
41 prev_last_update_id: u64,
42 first_update_id: u64,
43 },
44}
45
46impl DataError {
47 #[allow(clippy::match_like_matches_macro)]
49 pub fn is_terminal(&self) -> bool {
50 match self {
51 DataError::InvalidSequence { .. } => true,
52 _ => false,
53 }
54 }
55}
56
57impl From<SocketError> for DataError {
58 fn from(value: SocketError) -> Self {
59 Self::Socket(value.to_string())
60 }
61}
62
63#[cfg(test)]
64mod tests {
65 use super::*;
66
67 #[test]
68 fn test_data_error_is_terminal() {
69 struct TestCase {
70 input: DataError,
71 expected: bool,
72 }
73
74 let tests = vec![
75 TestCase {
76 input: DataError::InvalidSequence {
78 prev_last_update_id: 0,
79 first_update_id: 0,
80 },
81 expected: true,
82 },
83 TestCase {
84 input: DataError::from(SocketError::Sink),
86 expected: false,
87 },
88 ];
89
90 for (index, test) in tests.into_iter().enumerate() {
91 let actual = test.input.is_terminal();
92 assert_eq!(actual, test.expected, "TC{} failed", index);
93 }
94 }
95}