Skip to content

Commit 90316d7

Browse files
committed
feature: Add a route for immutable-files-restored
1 parent a9886c5 commit 90316d7

File tree

5 files changed

+273
-3
lines changed

5 files changed

+273
-3
lines changed

mithril-aggregator/src/http_server/routes/statistics_routes.rs

+178-3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use crate::http_server::routes::router::RouterState;
66
pub fn routes(
77
router_state: &RouterState,
88
) -> impl Filter<Extract = (impl warp::Reply,), Error = warp::Rejection> + Clone {
9-
post_statistics(router_state)
9+
post_statistics(router_state).or(post_cardano_database_immutable_files_restored(router_state))
1010
}
1111

1212
/// POST /statistics/snapshot
@@ -22,12 +22,27 @@ fn post_statistics(
2222
.and_then(handlers::post_snapshot_statistics)
2323
}
2424

25+
/// POST /statistics/cardano-database/immutable-files-restored
26+
fn post_cardano_database_immutable_files_restored(
27+
router_state: &RouterState,
28+
) -> impl Filter<Extract = (impl warp::Reply,), Error = warp::Rejection> + Clone {
29+
warp::path!("statistics" / "cardano-database" / "immutable-files-restored")
30+
.and(warp::post())
31+
.and(warp::body::json())
32+
.and(middlewares::with_logger(router_state))
33+
.and(middlewares::with_event_transmitter(router_state))
34+
.and(middlewares::with_metrics_service(router_state))
35+
.and_then(handlers::post_cardano_database_immutable_files_restored)
36+
}
37+
2538
mod handlers {
2639
use slog::warn;
2740
use std::{convert::Infallible, sync::Arc};
2841
use warp::http::StatusCode;
2942

30-
use mithril_common::messages::SnapshotDownloadMessage;
43+
use mithril_common::messages::{
44+
CardanoDatabaseImmutableFilesRestoredMessage, SnapshotDownloadMessage,
45+
};
3146

3247
use crate::event_store::{EventMessage, TransmitterService};
3348
use crate::http_server::routes::reply;
@@ -60,13 +75,53 @@ mod handlers {
6075
Ok(_) => Ok(reply::empty(StatusCode::CREATED)),
6176
}
6277
}
78+
79+
pub async fn post_cardano_database_immutable_files_restored(
80+
message: CardanoDatabaseImmutableFilesRestoredMessage,
81+
logger: slog::Logger,
82+
event_transmitter: Arc<TransmitterService<EventMessage>>,
83+
metrics_service: Arc<MetricsService>,
84+
) -> Result<impl warp::Reply, Infallible> {
85+
metrics_service
86+
.get_cardano_database_immutable_files_restored()
87+
.increment();
88+
89+
transmit_event_message(
90+
message,
91+
logger,
92+
event_transmitter,
93+
"cardano_database_immutable_files_restored",
94+
)
95+
.await
96+
}
97+
98+
async fn transmit_event_message(
99+
message: CardanoDatabaseImmutableFilesRestoredMessage,
100+
logger: slog::Logger,
101+
event_transmitter: Arc<TransmitterService<EventMessage>>,
102+
action: &str,
103+
) -> Result<impl warp::Reply, Infallible> {
104+
let headers: Vec<(&str, &str)> = Vec::new();
105+
106+
let message = EventMessage::new("HTTP::statistics", action, &message, headers);
107+
108+
match event_transmitter.try_send(message.clone()) {
109+
Err(e) => {
110+
warn!(logger, "Event message error"; "error" => ?e);
111+
Ok(reply::internal_server_error(e))
112+
}
113+
Ok(_) => Ok(reply::empty(StatusCode::CREATED)),
114+
}
115+
}
63116
}
64117

65118
#[cfg(test)]
66119
mod tests {
67120
use super::*;
68121

69-
use mithril_common::messages::SnapshotDownloadMessage;
122+
use mithril_common::messages::{
123+
CardanoDatabaseImmutableFilesRestoredMessage, SnapshotDownloadMessage,
124+
};
70125
use mithril_common::test_utils::apispec::APISpec;
71126

72127
use std::sync::Arc;
@@ -151,4 +206,124 @@ mod tests {
151206
.get()
152207
);
153208
}
209+
210+
mod post_cardano_database_immutable_files_restored {
211+
use tokio::sync::mpsc::UnboundedReceiver;
212+
use warp::hyper::body::Bytes;
213+
214+
use crate::{event_store::EventMessage, DependencyContainer};
215+
216+
use super::*;
217+
218+
const HTTP_METHOD: Method = Method::POST;
219+
const PATH: &str = "/statistics/cardano-database/immutable-files-restored";
220+
221+
async fn setup_dependencies() -> (Arc<DependencyContainer>, UnboundedReceiver<EventMessage>)
222+
{
223+
let config = Configuration::new_sample();
224+
let mut builder = DependenciesBuilder::new_with_stdout_logger(config);
225+
let rx = builder.get_event_transmitter_receiver().await.unwrap();
226+
let dependency_manager = Arc::new(builder.build_dependency_container().await.unwrap());
227+
(dependency_manager, rx)
228+
}
229+
230+
async fn send_request(
231+
dependency_manager: &Arc<DependencyContainer>,
232+
message: &CardanoDatabaseImmutableFilesRestoredMessage,
233+
) -> warp::http::Response<Bytes> {
234+
request()
235+
.method(HTTP_METHOD.as_str())
236+
.json(message)
237+
.path(PATH)
238+
.reply(&setup_router(RouterState::new_with_dummy_config(
239+
dependency_manager.clone(),
240+
)))
241+
.await
242+
}
243+
244+
#[tokio::test]
245+
async fn conform_to_open_api_when_created() {
246+
let (dependency_manager, _rx) = setup_dependencies().await;
247+
248+
let message = CardanoDatabaseImmutableFilesRestoredMessage::dummy();
249+
250+
let response = send_request(&dependency_manager, &message).await;
251+
252+
let result = APISpec::verify_conformity(
253+
APISpec::get_all_spec_files(),
254+
HTTP_METHOD.as_str(),
255+
PATH,
256+
"application/json",
257+
&message,
258+
&response,
259+
&StatusCode::CREATED,
260+
);
261+
262+
result.unwrap();
263+
}
264+
265+
#[tokio::test]
266+
async fn conform_to_open_api_when_server_error() {
267+
let (dependency_manager, mut rx) = setup_dependencies().await;
268+
rx.close();
269+
270+
let message = CardanoDatabaseImmutableFilesRestoredMessage::dummy();
271+
let response = request()
272+
.method(HTTP_METHOD.as_str())
273+
.json(&message)
274+
.path(PATH)
275+
.reply(&setup_router(RouterState::new_with_dummy_config(
276+
dependency_manager.clone(),
277+
)))
278+
.await;
279+
280+
APISpec::verify_conformity(
281+
APISpec::get_all_spec_files(),
282+
HTTP_METHOD.as_str(),
283+
PATH,
284+
"application/json",
285+
&message,
286+
&response,
287+
&StatusCode::INTERNAL_SERVER_ERROR,
288+
)
289+
.unwrap();
290+
}
291+
292+
#[tokio::test]
293+
async fn should_send_event() {
294+
let (dependency_manager, mut rx) = setup_dependencies().await;
295+
296+
send_request(
297+
&dependency_manager,
298+
&CardanoDatabaseImmutableFilesRestoredMessage::dummy(),
299+
)
300+
.await;
301+
302+
let _ = rx.try_recv().unwrap();
303+
}
304+
305+
#[tokio::test]
306+
async fn increments_metric() {
307+
let (dependency_manager, _rx) = setup_dependencies().await;
308+
309+
let initial_counter_value = dependency_manager
310+
.metrics_service
311+
.get_cardano_database_immutable_files_restored()
312+
.get();
313+
314+
send_request(
315+
&dependency_manager,
316+
&CardanoDatabaseImmutableFilesRestoredMessage::dummy(),
317+
)
318+
.await;
319+
320+
assert_eq!(
321+
initial_counter_value + 1,
322+
dependency_manager
323+
.metrics_service
324+
.get_cardano_database_immutable_files_restored()
325+
.get()
326+
);
327+
}
328+
}
154329
}

mithril-aggregator/src/metrics/service.rs

+16
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,22 @@ build_metrics_service!(
1818
"mithril_aggregator_cardano_db_total_restoration_since_startup",
1919
"Number of Cardano immutable files full restorations since startup on a Mithril aggregator node"
2020
),
21+
cardano_database_immutable_files_restored:MetricCounter(
22+
"mithril_aggregator_cardano_db_immutable_files_restored_since_startup",
23+
"Number of Cardano immutable files restored since startup on a Mithril aggregator node"
24+
),
25+
cardano_database_ancillary_files_restored:MetricCounter(
26+
"mithril_aggregator_cardano_db_ancillary_files_restored_since_startup",
27+
"Number of Cardano ancillary files restored since startup on a Mithril aggregator node"
28+
),
29+
cardano_database_full_restoration_since_startup:MetricCounter(
30+
"mithril_aggregator_cardano_db_full_restoration_since_startup",
31+
"Number of full Cardano database restoration since startup on a Mithril aggregator node"
32+
),
33+
cardano_database_partial_restoration_since_startup:MetricCounter(
34+
"mithril_aggregator_cardano_db_partial_restoration_since_startup",
35+
"Number of partial Cardano database restoration since startup on a Mithril aggregator node"
36+
),
2137
artifact_detail_cardano_database_total_served_since_startup:MetricCounter(
2238
"mithril_aggregator_artifact_detail_cardano_database_total_served_since_startup",
2339
"Number of Cardano database artifact details served since startup on a Mithril aggregator node"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
use serde::{Deserialize, Serialize};
2+
3+
/// Message structure of an immutable files restoration
4+
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
5+
pub struct CardanoDatabaseImmutableFilesRestoredMessage {
6+
/// Number of immutable files restored.
7+
pub nb_immutable_files: u64,
8+
}
9+
10+
impl CardanoDatabaseImmutableFilesRestoredMessage {
11+
/// Return a dummy test entity (test-only).
12+
pub fn dummy() -> Self {
13+
Self {
14+
nb_immutable_files: 34,
15+
}
16+
}
17+
}
18+
19+
#[cfg(test)]
20+
mod tests {
21+
use super::*;
22+
23+
const CURRENT_JSON: &str = r#"{
24+
"nb_immutable_files": 62
25+
},
26+
}"#;
27+
28+
fn golden_message_current() -> SnapshotMessage {
29+
SnapshotMessage {
30+
nb_immutable_files: 62,
31+
}
32+
}
33+
34+
#[test]
35+
fn test_current_json_deserialized_into_current_message() {
36+
let json = CURRENT_JSON;
37+
let message: CardanoDatabaseImmutableFilesRestoredMessage =
38+
serde_json::from_str(json).unwrap();
39+
40+
assert_eq!(golden_message_current(), message);
41+
}
42+
}

mithril-common/src/messages/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ mod aggregator_features;
44
mod aggregator_status;
55
mod cardano_database;
66
mod cardano_database_digest_list;
7+
mod cardano_database_immutable_files_restored;
78
mod cardano_database_list;
89
mod cardano_stake_distribution;
910
mod cardano_stake_distribution_list;
@@ -32,6 +33,7 @@ pub use cardano_database::{ArtifactsLocationsMessagePart, CardanoDatabaseSnapsho
3233
pub use cardano_database_digest_list::{
3334
CardanoDatabaseDigestListItemMessage, CardanoDatabaseDigestListMessage,
3435
};
36+
pub use cardano_database_immutable_files_restored::CardanoDatabaseImmutableFilesRestoredMessage;
3537
pub use cardano_database_list::{
3638
CardanoDatabaseSnapshotListItemMessage, CardanoDatabaseSnapshotListMessage,
3739
};

openapi.yaml

+35
Original file line numberDiff line numberDiff line change
@@ -746,6 +746,26 @@ paths:
746746
schema:
747747
$ref: "#/components/schemas/Error"
748748

749+
/statistics/cardano-database/immutable-files-restored:
750+
post:
751+
summary: Records immutable files restored event
752+
description: Records immutable files restored event
753+
requestBody:
754+
description: Immutable files restored message
755+
required: true
756+
content:
757+
application/json:
758+
schema:
759+
$ref: "#/components/schemas/CardanoDatabaseImmutableFilesRestoredMessage"
760+
responses:
761+
"201":
762+
description: Event successfully recorded
763+
default:
764+
description: Record event bad request
765+
content:
766+
application/json:
767+
schema:
768+
$ref: "#/components/schemas/Error"
749769
components:
750770
schemas:
751771
AggregatorStatusMessage:
@@ -1880,6 +1900,21 @@ components:
18801900
"cardano_node_version": "1.0.0"
18811901
}
18821902

1903+
CardanoDatabaseImmutableFilesRestoredMessage:
1904+
description: CardanoDatabaseImmutableFilesRestoredMessage represents a Cardano database immutable files restored event
1905+
type: object
1906+
additionalProperties: false
1907+
required:
1908+
- nb_immutable_files
1909+
properties:
1910+
nb_immutable_files:
1911+
description: Number of immutable files restored
1912+
type: integer
1913+
examples:
1914+
- {
1915+
"nb_immutable_files": 15
1916+
}
1917+
18831918
CardanoDatabaseArtifactsLocationsMessagePart:
18841919
description: CardanoDatabaseArtifactsLocationsMessagePart represents the locations of the Cardano database artifacts
18851920
type: object

0 commit comments

Comments
 (0)