1use std::sync::{Arc, Mutex};
4
5use bytes::Bytes;
6
7use crate::{
8 connect_client::ConnectClient,
9 error::KrabkaError,
10 messaging::MessagingClient,
11 stubs::{AuthClient, BlobClient, DatabaseClient, QueuesClient},
12};
13
14#[derive(Debug, Clone)]
16pub struct KrabkaClient {
17 pub(crate) inner: Arc<ClientInner>,
18}
19
20#[derive(Debug)]
21pub(crate) struct ClientInner {
22 pub(crate) endpoint: String,
23 pub(crate) bearer: Option<String>,
24 pub(crate) connect: ConnectClient,
25 pub(crate) mock: Mutex<MockState>,
26}
27
28#[derive(Debug, Default)]
30pub(crate) struct MockState {
31 pub(crate) messages: Vec<MockMessage>,
32 pub(crate) queue_sessions: Vec<MockQueueSession>,
33 pub(crate) queue_states: Vec<MockQueueMessageState>,
34}
35
36#[derive(Debug, Clone)]
38pub(crate) struct MockMessage {
39 pub(crate) topic: String,
40 pub(crate) partition: i32,
41 pub(crate) offset: i64,
42 pub(crate) value: Bytes,
43 pub(crate) headers: Vec<(String, Option<Bytes>)>,
44}
45
46#[derive(Debug, Clone, Default)]
48pub(crate) struct MockQueueSession {
49 pub(crate) id: String,
50 pub(crate) topic: String,
51 pub(crate) group: String,
52 pub(crate) max_messages: u32,
53}
54
55#[derive(Debug, Clone, PartialEq, Eq)]
57pub(crate) struct MockQueueDelivery {
58 pub(crate) topic: String,
59 pub(crate) partition: i32,
60 pub(crate) offset: i64,
61}
62
63#[derive(Debug, Clone, PartialEq, Eq)]
65pub(crate) struct MockQueueMessageState {
66 pub(crate) group: String,
67 pub(crate) delivery: MockQueueDelivery,
68 pub(crate) disposition: MockQueueDisposition,
69 pub(crate) delivery_count: i32,
70}
71
72#[derive(Debug, Clone, PartialEq, Eq)]
74pub(crate) enum MockQueueDisposition {
75 Available,
76 Acquired(String),
77 Accepted,
78 Rejected,
79}
80
81impl KrabkaClient {
82 #[must_use]
84 pub fn builder() -> KrabkaClientBuilder {
85 KrabkaClientBuilder::default()
86 }
87
88 pub fn new(endpoint: impl Into<String>) -> Result<Self, KrabkaError> {
95 Self::builder().endpoint(endpoint).build()
96 }
97
98 #[must_use]
100 pub fn messaging(&self) -> MessagingClient {
101 MessagingClient::new(self.clone())
102 }
103
104 #[must_use]
106 pub fn queues(&self) -> QueuesClient {
107 QueuesClient::new(self.clone())
108 }
109
110 #[must_use]
112 pub fn database(&self) -> DatabaseClient {
113 DatabaseClient::new()
114 }
115
116 #[must_use]
118 pub fn auth(&self) -> AuthClient {
119 AuthClient::new(self.inner.bearer.clone())
120 }
121
122 #[must_use]
124 pub fn blob(&self) -> BlobClient {
125 BlobClient::new()
126 }
127
128 pub(crate) fn is_mock(&self) -> bool {
129 self.inner.endpoint.starts_with("mock://")
130 }
131
132 pub(crate) fn is_unreachable(&self) -> bool {
133 self.inner.endpoint.starts_with("unreachable://")
134 }
135}
136
137#[derive(Debug, Default)]
139pub struct KrabkaClientBuilder {
140 endpoint: Option<String>,
141 bearer: Option<String>,
142}
143
144impl KrabkaClientBuilder {
145 #[must_use]
147 pub fn endpoint(mut self, endpoint: impl Into<String>) -> Self {
148 self.endpoint = Some(endpoint.into());
149 self
150 }
151
152 #[must_use]
154 pub fn bearer_token(mut self, bearer: impl Into<String>) -> Self {
155 self.bearer = Some(bearer.into());
156 self
157 }
158
159 pub fn build(self) -> Result<KrabkaClient, KrabkaError> {
165 let endpoint = self
166 .endpoint
167 .ok_or_else(|| KrabkaError::InvalidArgument("endpoint is required".into()))?;
168 Ok(KrabkaClient {
169 inner: Arc::new(ClientInner {
170 connect: ConnectClient::new(endpoint.clone(), self.bearer.clone()),
171 endpoint,
172 bearer: self.bearer,
173 mock: Mutex::new(MockState::default()),
174 }),
175 })
176 }
177}