Skip to content

Commit b2bc7fd

Browse files
committed
add snapshot statistics route
1 parent e432c59 commit b2bc7fd

File tree

5 files changed

+150
-0
lines changed

5 files changed

+150
-0
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"git.ignoreLimitWarning": true
3+
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ mod reply;
66
pub mod router;
77
mod signatures_routes;
88
mod signer_routes;
9+
mod statistics;

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ use warp::http::Method;
1414
use warp::reject::Reject;
1515
use warp::{Filter, Rejection, Reply};
1616

17+
use super::statistics;
18+
1719
#[derive(Debug)]
1820
pub struct VersionMismatchError;
1921

@@ -49,6 +51,7 @@ pub fn routes(
4951
.or(signer_routes::routes(dependency_manager.clone()))
5052
.or(signatures_routes::routes(dependency_manager.clone()))
5153
.or(epoch_routes::routes(dependency_manager.clone()))
54+
.or(statistics::routes(dependency_manager.clone()))
5255
.with(cors),
5356
)
5457
.recover(handle_custom)
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
use mithril_common::MITHRIL_SIGNER_VERSION_HEADER;
2+
use std::sync::Arc;
3+
use warp::Filter;
4+
5+
use crate::http_server::routes::middlewares;
6+
use crate::DependencyContainer;
7+
8+
pub fn routes(
9+
dependency_manager: Arc<DependencyContainer>,
10+
) -> impl Filter<Extract = (impl warp::Reply,), Error = warp::Rejection> + Clone {
11+
post_statistics(dependency_manager)
12+
}
13+
14+
/// POST /statistics/snapshot
15+
fn post_statistics(
16+
dependency_manager: Arc<DependencyContainer>,
17+
) -> impl Filter<Extract = (impl warp::Reply,), Error = warp::Rejection> + Clone {
18+
warp::path!("statistics" / "snapshot")
19+
.and(warp::post())
20+
.and(warp::header::optional::<String>(
21+
MITHRIL_SIGNER_VERSION_HEADER,
22+
))
23+
.and(warp::body::json())
24+
.and(middlewares::with_event_transmitter(
25+
dependency_manager.clone(),
26+
))
27+
.and_then(handlers::post_snapshot_statistics)
28+
}
29+
30+
mod handlers {
31+
use std::{convert::Infallible, sync::Arc};
32+
33+
use mithril_common::messages::SnapshotMessage;
34+
use reqwest::StatusCode;
35+
36+
use crate::event_store::{EventMessage, TransmitterService};
37+
use crate::http_server::routes::reply;
38+
39+
pub async fn post_snapshot_statistics(
40+
signer_node_version: Option<String>,
41+
snapshot_message: SnapshotMessage,
42+
event_transmitter: Arc<TransmitterService<EventMessage>>,
43+
) -> Result<impl warp::Reply, Infallible> {
44+
let headers: Vec<(&str, &str)> = signer_node_version
45+
.as_ref()
46+
.map(|v| ("signer-node-version", v.as_str()))
47+
.into_iter()
48+
.collect();
49+
let _ = event_transmitter.send_event_message(
50+
"HTTP::statistics",
51+
"snapshot_downloaded",
52+
&snapshot_message,
53+
headers,
54+
);
55+
56+
Ok(reply::empty(StatusCode::CREATED))
57+
}
58+
}
59+
60+
#[cfg(test)]
61+
mod tests {
62+
use super::*;
63+
64+
use mithril_common::messages::SnapshotMessage;
65+
use mithril_common::test_utils::apispec::APISpec;
66+
67+
use warp::{http::Method, test::request};
68+
69+
use crate::{
70+
dependency_injection::DependenciesBuilder, http_server::SERVER_BASE_PATH, Configuration,
71+
};
72+
73+
fn setup_router(
74+
dependency_manager: Arc<DependencyContainer>,
75+
) -> impl Filter<Extract = (impl warp::Reply,), Error = warp::Rejection> + Clone {
76+
let cors = warp::cors()
77+
.allow_any_origin()
78+
.allow_headers(vec!["content-type"])
79+
.allow_methods(vec![Method::GET, Method::POST, Method::OPTIONS]);
80+
81+
warp::any()
82+
.and(warp::path(SERVER_BASE_PATH))
83+
.and(routes(dependency_manager).with(cors))
84+
}
85+
86+
#[tokio::test]
87+
async fn post_statistics_ok() {
88+
let config = Configuration::new_sample();
89+
let mut builder = DependenciesBuilder::new(config);
90+
let mut rx = builder.get_event_transmitter_receiver().await.unwrap();
91+
let dependency_manager = builder.build_dependency_container().await.unwrap();
92+
let snapshot_message = SnapshotMessage::dummy();
93+
94+
let method = Method::POST.as_str();
95+
let path = "/statistics/snapshot";
96+
97+
let response = request()
98+
.method(method)
99+
.json(&snapshot_message)
100+
.path(&format!("/{SERVER_BASE_PATH}{path}"))
101+
.reply(&setup_router(Arc::new(dependency_manager)))
102+
.await;
103+
104+
APISpec::verify_conformity(
105+
APISpec::get_all_spec_files(),
106+
method,
107+
path,
108+
"application/json",
109+
&snapshot_message,
110+
&response,
111+
);
112+
113+
let _ = rx.try_recv().unwrap();
114+
}
115+
}

openapi.yaml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,34 @@ paths:
360360
application/json:
361361
schema:
362362
$ref: "#/components/schemas/Error"
363+
/statistics/snapshot:
364+
post:
365+
summary: Increments download statistics
366+
description: Increments snapshot download statistics
367+
requestBody:
368+
description: Downloaded snapshot
369+
required: true
370+
content:
371+
application/json:
372+
schema:
373+
$ref: "#/components/schemas/SnapshotMessage"
374+
responses:
375+
"201":
376+
description: Statistic succesfully posted
377+
"400":
378+
description: Increments download statistics bad request
379+
content:
380+
application/json:
381+
schema:
382+
$ref: "#/components/schemas/Error"
383+
"412":
384+
description: API version mismatch
385+
default:
386+
description: Snapshot download statistics error
387+
content:
388+
application/json:
389+
schema:
390+
$ref: "#/components/schemas/Error"
363391

364392
components:
365393
schemas:

0 commit comments

Comments
 (0)