mithril_aggregator/database/record/
open_message.rs1use chrono::{DateTime, Utc};
2use sqlite::Row;
3use uuid::Uuid;
4
5use mithril_common::entities::{Epoch, ProtocolMessage, SignedEntityType};
6use mithril_persistence::database::Hydrator;
7use mithril_persistence::sqlite::{HydrationError, Projection, SqLiteEntity};
8
9#[derive(Debug, Clone, PartialEq, Eq)]
15pub struct OpenMessageRecord {
16 pub open_message_id: Uuid,
18
19 pub epoch: Epoch,
21
22 pub signed_entity_type: SignedEntityType,
24
25 pub protocol_message: ProtocolMessage,
27
28 pub is_certified: bool,
30
31 pub is_expired: bool,
33
34 pub created_at: DateTime<Utc>,
36
37 pub expires_at: Option<DateTime<Utc>>,
39}
40
41impl OpenMessageRecord {
42 pub fn new_id() -> Uuid {
44 Uuid::new_v4()
45 }
46}
47
48impl SqLiteEntity for OpenMessageRecord {
49 fn hydrate(row: Row) -> Result<Self, HydrationError>
50 where
51 Self: Sized,
52 {
53 let open_message_id = row.read::<&str, _>(0);
54 let open_message_id = Uuid::parse_str(open_message_id).map_err(|e| {
55 HydrationError::InvalidData(format!(
56 "Invalid UUID in open_message.open_message_id: '{open_message_id}'. Error: {e}"
57 ))
58 })?;
59 let protocol_message = row.read::<&str, _>(4);
60 let protocol_message = serde_json::from_str(protocol_message).map_err(|e| {
61 HydrationError::InvalidData(format!(
62 "Invalid protocol message JSON representation '{protocol_message}'. Error: {e}"
63 ))
64 })?;
65 let epoch_settings_id = row.read::<i64, _>(1);
66 let epoch_val = u64::try_from(epoch_settings_id)
67 .map_err(|e| panic!("Integer field open_message.epoch_setting_id (value={epoch_settings_id}) is incompatible with u64 Epoch representation. Error = {e}"))?;
68 let beacon_str = Hydrator::read_signed_entity_beacon_column(&row, 2);
69 let signed_entity_type_id = usize::try_from(row.read::<i64, _>(3)).map_err(|e| {
70 panic!(
71 "Integer field open_message.signed_entity_type_id cannot be turned into usize: {e}"
72 )
73 })?;
74 let signed_entity_type =
75 Hydrator::hydrate_signed_entity_type(signed_entity_type_id, &beacon_str)?;
76 let is_certified = row.read::<i64, _>(5) != 0;
77 let datetime = &row.read::<&str, _>(7);
78 let created_at =
79 DateTime::parse_from_rfc3339(datetime).map_err(|e| {
80 HydrationError::InvalidData(format!(
81 "Could not turn open_message.created_at field value '{datetime}' to rfc3339 Datetime. Error: {e}"
82 ))
83 })?.with_timezone(&Utc);
84 let is_expired = row.read::<i64, _>(6) != 0;
85 let datetime = &row.read::<Option<&str>, _>(8);
86 let expires_at = datetime.map(|datetime| DateTime::parse_from_rfc3339(datetime).map_err(|e| {
87 HydrationError::InvalidData(format!(
88 "Could not turn open_message.expires_at field value '{datetime}' to rfc3339 Datetime. Error: {e}"
89 ))
90 })).transpose()?.map(|datetime| datetime.with_timezone(&Utc));
91 let open_message = Self {
92 open_message_id,
93 epoch: Epoch(epoch_val),
94 signed_entity_type,
95 protocol_message,
96 is_certified,
97 is_expired,
98 created_at,
99 expires_at,
100 };
101
102 Ok(open_message)
103 }
104
105 fn get_projection() -> Projection {
106 Projection::from(&[
107 (
108 "open_message_id",
109 "{:open_message:}.open_message_id",
110 "text",
111 ),
112 (
113 "epoch_setting_id",
114 "{:open_message:}.epoch_setting_id",
115 "int",
116 ),
117 ("beacon", "{:open_message:}.beacon", "text"),
118 (
119 "signed_entity_type_id",
120 "{:open_message:}.signed_entity_type_id",
121 "int",
122 ),
123 (
124 "protocol_message",
125 "{:open_message:}.protocol_message",
126 "text",
127 ),
128 ("is_certified", "{:open_message:}.is_certified", "bool"),
129 ("is_expired", "{:open_message:}.is_expired", "bool"),
130 ("created_at", "{:open_message:}.created_at", "text"),
131 ("expires_at", "{:open_message:}.expires_at", "text"),
132 ])
133 }
134}