1use std::{
2 fmt,
3 hash::Hash,
4 net::SocketAddr,
5 ops::Deref,
6 time::{Duration, SystemTime},
7};
8
9use crate::api::SqliteValue;
10use foca::Identity;
11use rusqlite::{
12 ToSql,
13 types::{FromSql, ToSqlOutput},
14};
15use serde::{Deserialize, Serialize};
16use speedy::{Context, Readable, Reader, Writable, Writer};
17use uhlc::NTP64;
18use uuid::Uuid;
19
20use crate::broadcast::Timestamp;
21
22#[derive(
23 Debug, Default, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize,
24)]
25#[serde(transparent)]
26pub struct ActorId(pub Uuid);
27
28impl ActorId {
29 pub fn to_bytes(&self) -> [u8; 16] {
30 self.0.into_bytes()
31 }
32
33 pub fn as_bytes(&self) -> &[u8; 16] {
34 self.0.as_bytes()
35 }
36
37 pub fn from_bytes(bytes: [u8; 16]) -> Self {
38 Self(Uuid::from_bytes(bytes))
39 }
40}
41
42impl TryFrom<ActorId> for uhlc::ID {
43 type Error = uhlc::SizeError;
44
45 fn try_from(value: ActorId) -> Result<Self, Self::Error> {
46 value.as_bytes().try_into()
47 }
48}
49
50impl Deref for ActorId {
51 type Target = Uuid;
52
53 fn deref(&self) -> &Self::Target {
54 &self.0
55 }
56}
57
58impl fmt::Display for ActorId {
59 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
60 self.0.as_simple().fmt(f)
61 }
62}
63
64const UUID_SIZE: usize = 16;
65
66#[derive(Debug, thiserror::Error)]
67pub enum SqliteValueToActorIdError {
68 #[error("sqlite value had wrong type")]
69 WrongType,
70 #[error("wrong number of bytes, requires exactly 16 bytes")]
71 WrongNumberOfBytes,
72}
73
74impl TryFrom<&SqliteValue> for ActorId {
75 type Error = SqliteValueToActorIdError;
76
77 fn try_from(value: &SqliteValue) -> Result<Self, Self::Error> {
78 match value.as_blob() {
79 Some(v) => {
80 if v.len() != UUID_SIZE {
81 Err(SqliteValueToActorIdError::WrongNumberOfBytes)
82 } else {
83 Ok(ActorId::from_bytes(v.try_into().unwrap()))
84 }
85 }
86 None => Err(SqliteValueToActorIdError::WrongType),
87 }
88 }
89}
90
91impl<'a, C> Readable<'a, C> for ActorId
92where
93 C: Context,
94{
95 #[inline]
96 fn read_from<R: Reader<'a, C>>(reader: &mut R) -> Result<Self, C::Error> {
97 Ok(ActorId(Uuid::from_bytes(reader.read_value()?)))
98 }
99
100 #[inline]
101 fn minimum_bytes_needed() -> usize {
102 UUID_SIZE
103 }
104}
105
106impl<C> Writable<C> for ActorId
107where
108 C: Context,
109{
110 #[inline]
111 fn write_to<T: ?Sized + Writer<C>>(&self, writer: &mut T) -> Result<(), C::Error> {
112 writer.write_bytes(self.0.as_bytes())
113 }
114
115 #[inline]
116 fn bytes_needed(&self) -> Result<usize, C::Error> {
117 Ok(UUID_SIZE)
118 }
119}
120
121impl ToSql for ActorId {
122 fn to_sql(&self) -> rusqlite::Result<ToSqlOutput<'_>> {
123 self.0.to_sql()
124 }
125}
126
127impl FromSql for ActorId {
128 fn column_result(value: rusqlite::types::ValueRef<'_>) -> rusqlite::types::FromSqlResult<Self> {
129 Ok(Self(FromSql::column_result(value)?))
130 }
131}
132
133#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
134pub struct Actor {
135 id: ActorId,
136 addr: SocketAddr,
137 ts: Timestamp,
138 #[serde(default)]
139 cluster_id: ClusterId,
140}
141
142impl Hash for Actor {
143 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
144 self.id.hash(state);
145 self.addr.hash(state);
146 }
147}
148
149impl Actor {
150 pub fn new(id: ActorId, addr: SocketAddr, ts: Timestamp, cluster_id: ClusterId) -> Self {
151 Self {
152 id,
153 addr,
154 ts,
155 cluster_id,
156 }
157 }
158
159 pub fn id(&self) -> ActorId {
160 self.id
161 }
162 pub fn addr(&self) -> SocketAddr {
163 self.addr
164 }
165 pub fn ts(&self) -> Timestamp {
166 self.ts
167 }
168 pub fn cluster_id(&self) -> ClusterId {
169 self.cluster_id
170 }
171}
172
173impl From<SocketAddr> for Actor {
174 fn from(value: SocketAddr) -> Self {
175 Self::new(
176 ActorId(Uuid::nil()),
177 value,
178 Timestamp::zero(),
179 Default::default(),
180 )
181 }
182}
183
184pub struct ActorAddr {
185 id: ActorId,
186 addr: SocketAddr,
187}
188
189impl PartialEq for ActorAddr {
190 fn eq(&self, other: &Self) -> bool {
191 if self.id.is_nil() || other.id.is_nil() {
194 self.addr.eq(&other.addr)
195 } else {
196 self.id.eq(&other.id)
197 }
198 }
199}
200
201impl Identity for Actor {
202 type Addr = ActorAddr;
203
204 fn addr(&self) -> Self::Addr {
209 ActorAddr {
210 id: self.id,
211 addr: self.addr,
212 }
213 }
214
215 fn renew(&self) -> Option<Self> {
219 Some(Self {
220 id: self.id,
221 addr: self.addr,
222 ts: NTP64::from(duration_since_epoch()).into(),
223 cluster_id: self.cluster_id,
224 })
225 }
226
227 fn win_addr_conflict(&self, adversary: &Self) -> bool {
228 self.ts > adversary.ts
229 }
230}
231
232fn duration_since_epoch() -> Duration {
233 SystemTime::now()
234 .duration_since(SystemTime::UNIX_EPOCH)
235 .expect("could not generate duration since unix epoch")
236}
237
238#[derive(
239 Debug, Default, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize,
240)]
241#[serde(transparent)]
242pub struct ClusterId(pub u16);
243
244impl fmt::Display for ClusterId {
245 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
246 self.0.fmt(f)
247 }
248}
249
250impl<'a, C> Readable<'a, C> for ClusterId
251where
252 C: Context,
253{
254 #[inline]
255 fn read_from<R: Reader<'a, C>>(reader: &mut R) -> Result<Self, C::Error> {
256 Ok(ClusterId(u16::read_from(reader)?))
257 }
258
259 #[inline]
260 fn minimum_bytes_needed() -> usize {
261 2
262 }
263}
264
265impl<C> Writable<C> for ClusterId
266where
267 C: Context,
268{
269 #[inline]
270 fn write_to<T: ?Sized + Writer<C>>(&self, writer: &mut T) -> Result<(), C::Error> {
271 self.0.write_to(writer)
272 }
273
274 #[inline]
275 fn bytes_needed(&self) -> Result<usize, C::Error> {
276 Writable::<C>::bytes_needed(&self.0)
277 }
278}
279
280impl ToSql for ClusterId {
281 fn to_sql(&self) -> rusqlite::Result<ToSqlOutput<'_>> {
282 self.0.to_sql()
283 }
284}
285
286impl FromSql for ClusterId {
287 fn column_result(value: rusqlite::types::ValueRef<'_>) -> rusqlite::types::FromSqlResult<Self> {
288 Ok(Self(FromSql::column_result(value)?))
289 }
290}