mithril_aggregator_client/query/get/
get_cardano_database_list.rs1use async_trait::async_trait;
2use reqwest::StatusCode;
3use std::fmt::{Display, Formatter};
4
5use mithril_common::entities::EpochSpecifier;
6use mithril_common::messages::CardanoDatabaseSnapshotListMessage;
7
8use crate::AggregatorHttpClientResult;
9use crate::query::{AggregatorQuery, QueryContext, QueryMethod, ResponseExt};
10
11pub struct GetCardanoDatabaseListQuery {
13 scope: ListScope,
14}
15
16enum ListScope {
17 Latest,
19 Epoch(EpochSpecifier),
21}
22
23impl Display for ListScope {
24 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
25 match &self {
26 ListScope::Latest => {
27 write!(f, "latest")
28 }
29 ListScope::Epoch(specifier) => {
30 write!(f, "epoch({specifier})")
31 }
32 }
33 }
34}
35
36impl GetCardanoDatabaseListQuery {
37 pub fn latest() -> Self {
39 Self {
40 scope: ListScope::Latest,
41 }
42 }
43
44 pub fn for_epoch(epoch_specifier: EpochSpecifier) -> Self {
46 Self {
47 scope: ListScope::Epoch(epoch_specifier),
48 }
49 }
50}
51
52#[cfg_attr(target_family = "wasm", async_trait(?Send))]
53#[cfg_attr(not(target_family = "wasm"), async_trait)]
54impl AggregatorQuery for GetCardanoDatabaseListQuery {
55 type Response = CardanoDatabaseSnapshotListMessage;
56 type Body = ();
57
58 fn method() -> QueryMethod {
59 QueryMethod::Get
60 }
61
62 fn route(&self) -> String {
63 match &self.scope {
64 ListScope::Latest => "artifact/cardano-database".to_string(),
65 ListScope::Epoch(specifier) => {
66 format!("artifact/cardano-database/epoch/{specifier}")
67 }
68 }
69 }
70
71 async fn handle_response(
72 &self,
73 context: QueryContext,
74 ) -> AggregatorHttpClientResult<Self::Response> {
75 match context.response.status() {
76 StatusCode::OK => context.response.parse_json().await,
77 _ => Err(context.unhandled_status_code().await),
78 }
79 }
80}
81
82#[cfg(test)]
83mod tests {
84 use serde_json::json;
85
86 use mithril_common::entities::Epoch;
87 use mithril_common::messages::CardanoDatabaseSnapshotListItemMessage;
88 use mithril_common::test::double::Dummy;
89
90 use crate::AggregatorHttpClientError;
91 use crate::test::{assert_error_matches, setup_server_and_client};
92
93 use super::*;
94
95 #[tokio::test]
96 async fn test_latest_cardano_database_list_ok_200() {
97 let (server, client) = setup_server_and_client();
98 let expected_list = vec![
99 CardanoDatabaseSnapshotListItemMessage::dummy(),
100 CardanoDatabaseSnapshotListItemMessage::dummy(),
101 ];
102 let _server_mock = server.mock(|when, then| {
103 when.path("/artifact/cardano-database");
104 then.status(200).body(json!(expected_list).to_string());
105 });
106
107 let fetched_list = client.send(GetCardanoDatabaseListQuery::latest()).await.unwrap();
108
109 assert_eq!(expected_list, fetched_list);
110 }
111
112 #[tokio::test]
113 async fn test_specific_epoch_cardano_database_list_ok_200() {
114 let (server, client) = setup_server_and_client();
115 let expected_list = vec![
116 CardanoDatabaseSnapshotListItemMessage::dummy(),
117 CardanoDatabaseSnapshotListItemMessage::dummy(),
118 ];
119 let _server_mock = server.mock(|when, then| {
120 when.path("/artifact/cardano-database/epoch/12");
121 then.status(200).body(json!(expected_list).to_string());
122 });
123
124 let fetched_list = client
125 .send(GetCardanoDatabaseListQuery::for_epoch(
126 EpochSpecifier::Number(Epoch(12)),
127 ))
128 .await
129 .unwrap();
130
131 assert_eq!(expected_list, fetched_list);
132 }
133
134 #[tokio::test]
135 async fn test_latest_epoch_cardano_database_list_ok_200() {
136 let (server, client) = setup_server_and_client();
137 let expected_list = vec![
138 CardanoDatabaseSnapshotListItemMessage::dummy(),
139 CardanoDatabaseSnapshotListItemMessage::dummy(),
140 ];
141 let _server_mock = server.mock(|when, then| {
142 when.path("/artifact/cardano-database/epoch/latest");
143 then.status(200).body(json!(expected_list).to_string());
144 });
145
146 let fetched_list = client
147 .send(GetCardanoDatabaseListQuery::for_epoch(
148 EpochSpecifier::Latest,
149 ))
150 .await
151 .unwrap();
152
153 assert_eq!(expected_list, fetched_list);
154 }
155
156 #[tokio::test]
157 async fn test_latest_epoch_with_offset_cardano_database_list_ok_200() {
158 let (server, client) = setup_server_and_client();
159 let expected_list = vec![
160 CardanoDatabaseSnapshotListItemMessage::dummy(),
161 CardanoDatabaseSnapshotListItemMessage::dummy(),
162 ];
163 let _server_mock = server.mock(|when, then| {
164 when.path("/artifact/cardano-database/epoch/latest-3");
165 then.status(200).body(json!(expected_list).to_string());
166 });
167
168 let fetched_list = client
169 .send(GetCardanoDatabaseListQuery::for_epoch(
170 EpochSpecifier::LatestMinusOffset(3),
171 ))
172 .await
173 .unwrap();
174
175 assert_eq!(expected_list, fetched_list);
176 }
177
178 #[tokio::test]
179 async fn test_cardano_database_list_ko_500() {
180 let (server, client) = setup_server_and_client();
181 let _server_mock = server.mock(|when, then| {
182 when.any_request();
183 then.status(500).body("an error occurred");
184 });
185
186 let error = client.send(GetCardanoDatabaseListQuery::latest()).await.unwrap_err();
187
188 assert_error_matches!(error, AggregatorHttpClientError::RemoteServerTechnical(_));
189 }
190}