Skip to content

Commit bbaeb65

Browse files
committed
feature(protocol-config): put back aggregator_features route call
1 parent 34308a1 commit bbaeb65

File tree

1 file changed

+156
-46
lines changed

1 file changed

+156
-46
lines changed

internal/mithril-protocol-config/src/http_client/aggregator_client.rs

Lines changed: 156 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use mithril_common::{
1212
api_version::APIVersionProvider,
1313
entities::{ClientError, ServerError},
1414
logging::LoggerExtensions,
15-
messages::EpochSettingsMessage,
15+
messages::{AggregatorFeaturesMessage, EpochSettingsMessage},
1616
};
1717

1818
const JSON_CONTENT_TYPE: HeaderValue = HeaderValue::from_static("application/json");
@@ -124,6 +124,11 @@ pub trait AggregatorClient: Sync + Send {
124124
async fn retrieve_epoch_settings(
125125
&self,
126126
) -> Result<Option<EpochSettingsMessage>, AggregatorClientError>;
127+
128+
/// Retrieves aggregator features message from the aggregator
129+
async fn retrieve_aggregator_features(
130+
&self,
131+
) -> Result<AggregatorFeaturesMessage, AggregatorClientError>;
127132
}
128133

129134
/// AggregatorHTTPClient is a http client for an aggregator
@@ -244,6 +249,32 @@ impl AggregatorClient for AggregatorHTTPClient {
244249
Err(err) => Err(AggregatorClientError::RemoteServerUnreachable(anyhow!(err))),
245250
}
246251
}
252+
253+
async fn retrieve_aggregator_features(
254+
&self,
255+
) -> Result<AggregatorFeaturesMessage, AggregatorClientError> {
256+
debug!(self.logger, "Retrieve aggregator features message");
257+
let url = format!("{}/", self.aggregator_endpoint);
258+
let response = self
259+
.prepare_request_builder(self.prepare_http_client()?.get(url.clone()))
260+
.send()
261+
.await;
262+
263+
match response {
264+
Ok(response) => match response.status() {
265+
StatusCode::OK => {
266+
self.warn_if_api_version_mismatch(&response);
267+
268+
Ok(response
269+
.json::<AggregatorFeaturesMessage>()
270+
.await
271+
.map_err(|e| AggregatorClientError::JsonParseFailed(anyhow!(e)))?)
272+
}
273+
_ => Err(AggregatorClientError::from_response(response).await),
274+
},
275+
Err(err) => Err(AggregatorClientError::RemoteServerUnreachable(anyhow!(err))),
276+
}
277+
}
247278
}
248279

249280
#[cfg(test)]
@@ -258,19 +289,24 @@ pub(crate) mod dumb {
258289
/// It is driven by a Tester that controls the data it can return, and it can return its internal state for testing.
259290
pub struct DumbAggregatorClient {
260291
epoch_settings: RwLock<Option<EpochSettingsMessage>>,
292+
aggregator_features: RwLock<AggregatorFeaturesMessage>,
261293
}
262294

263-
// impl DumbAggregatorClient {
264-
// /// Return the last signer that called with the `register` method.
265-
// pub async fn get_last_registered_signer(&self) -> Option<Signer> {
266-
// self.last_registered_signer.read().await.clone()
267-
// }
268-
// }
295+
impl DumbAggregatorClient {
296+
pub async fn set_aggregator_features(
297+
&self,
298+
aggregator_features: AggregatorFeaturesMessage,
299+
) {
300+
let mut aggregator_features_writer = self.aggregator_features.write().await;
301+
*aggregator_features_writer = aggregator_features;
302+
}
303+
}
269304

270305
impl Default for DumbAggregatorClient {
271306
fn default() -> Self {
272307
Self {
273308
epoch_settings: RwLock::new(Some(EpochSettingsMessage::dummy())),
309+
aggregator_features: RwLock::new(AggregatorFeaturesMessage::dummy()),
274310
}
275311
}
276312
}
@@ -284,6 +320,13 @@ pub(crate) mod dumb {
284320

285321
Ok(epoch_settings)
286322
}
323+
324+
async fn retrieve_aggregator_features(
325+
&self,
326+
) -> Result<AggregatorFeaturesMessage, AggregatorClientError> {
327+
let aggregator_features = self.aggregator_features.read().await;
328+
Ok(aggregator_features.clone())
329+
}
287330
}
288331
}
289332

@@ -305,6 +348,17 @@ mod tests {
305348

306349
use super::*;
307350

351+
macro_rules! assert_is_error {
352+
($error:expr, $error_type:pat) => {
353+
assert!(
354+
matches!($error, $error_type),
355+
"Expected {} error, got '{:?}'.",
356+
stringify!($error_type),
357+
$error
358+
);
359+
};
360+
}
361+
308362
fn setup_client<U: Into<String>>(server_url: U) -> AggregatorHTTPClient {
309363
let discriminant_source = DummyApiVersionDiscriminantSource::new("dummy");
310364
let api_version_provider = APIVersionProvider::new(Arc::new(discriminant_source));
@@ -366,52 +420,108 @@ mod tests {
366420
};
367421
}
368422

369-
#[tokio::test]
370-
async fn test_epoch_settings_ok_200() {
371-
let (server, client) = setup_server_and_client();
372-
let epoch_settings_expected = EpochSettingsMessage::dummy();
373-
let _server_mock = server.mock(|when, then| {
374-
when.path("/epoch-settings");
375-
then.status(200).body(json!(epoch_settings_expected).to_string());
376-
});
423+
mod epoch_settings {
424+
use super::*;
377425

378-
let epoch_settings = client.retrieve_epoch_settings().await;
379-
epoch_settings.as_ref().expect("unexpected error");
380-
assert_eq!(epoch_settings_expected, epoch_settings.unwrap().unwrap());
381-
}
426+
#[tokio::test]
427+
async fn test_epoch_settings_ok_200() {
428+
let (server, client) = setup_server_and_client();
429+
let epoch_settings_expected = EpochSettingsMessage::dummy();
430+
let _server_mock = server.mock(|when, then| {
431+
when.path("/epoch-settings");
432+
then.status(200).body(json!(epoch_settings_expected).to_string());
433+
});
382434

383-
#[tokio::test]
384-
async fn test_epoch_settings_ko_500() {
385-
let (server, client) = setup_server_and_client();
386-
let _server_mock = server.mock(|when, then| {
387-
when.path("/epoch-settings");
388-
then.status(500).body("an error occurred");
389-
});
435+
let epoch_settings = client.retrieve_epoch_settings().await;
436+
epoch_settings.as_ref().expect("unexpected error");
437+
assert_eq!(epoch_settings_expected, epoch_settings.unwrap().unwrap());
438+
}
390439

391-
match client.retrieve_epoch_settings().await.unwrap_err() {
392-
AggregatorClientError::RemoteServerTechnical(_) => (),
393-
e => panic!("Expected Aggregator::RemoteServerTechnical error, got '{e:?}'."),
394-
};
440+
#[tokio::test]
441+
async fn test_epoch_settings_ko_500() {
442+
let (server, client) = setup_server_and_client();
443+
let _server_mock = server.mock(|when, then| {
444+
when.path("/epoch-settings");
445+
then.status(500).body("an error occurred");
446+
});
447+
448+
match client.retrieve_epoch_settings().await.unwrap_err() {
449+
AggregatorClientError::RemoteServerTechnical(_) => (),
450+
e => panic!("Expected Aggregator::RemoteServerTechnical error, got '{e:?}'."),
451+
};
452+
}
453+
454+
#[tokio::test]
455+
async fn test_epoch_settings_timeout() {
456+
let (server, mut client) = setup_server_and_client();
457+
client.timeout_duration = Some(Duration::from_millis(10));
458+
let _server_mock = server.mock(|when, then| {
459+
when.path("/epoch-settings");
460+
then.delay(Duration::from_millis(100));
461+
});
462+
463+
let error = client
464+
.retrieve_epoch_settings()
465+
.await
466+
.expect_err("retrieve_epoch_settings should fail");
467+
468+
assert!(
469+
matches!(error, AggregatorClientError::RemoteServerUnreachable(_)),
470+
"unexpected error type: {error:?}"
471+
);
472+
}
395473
}
396474

397-
#[tokio::test]
398-
async fn test_epoch_settings_timeout() {
399-
let (server, mut client) = setup_server_and_client();
400-
client.timeout_duration = Some(Duration::from_millis(10));
401-
let _server_mock = server.mock(|when, then| {
402-
when.path("/epoch-settings");
403-
then.delay(Duration::from_millis(100));
404-
});
475+
mod aggregator_features {
476+
use super::*;
405477

406-
let error = client
407-
.retrieve_epoch_settings()
408-
.await
409-
.expect_err("retrieve_epoch_settings should fail");
478+
#[tokio::test]
479+
async fn test_aggregator_features_ok_200() {
480+
let (server, client) = setup_server_and_client();
481+
let message_expected = AggregatorFeaturesMessage::dummy();
482+
let _server_mock = server.mock(|when, then| {
483+
when.path("/");
484+
then.status(200).body(json!(message_expected).to_string());
485+
});
410486

411-
assert!(
412-
matches!(error, AggregatorClientError::RemoteServerUnreachable(_)),
413-
"unexpected error type: {error:?}"
414-
);
487+
let message = client.retrieve_aggregator_features().await.unwrap();
488+
489+
assert_eq!(message_expected, message);
490+
}
491+
492+
#[tokio::test]
493+
async fn test_aggregator_features_ko_500() {
494+
let (server, client) = setup_server_and_client();
495+
set_returning_500(&server);
496+
497+
let error = client.retrieve_aggregator_features().await.unwrap_err();
498+
499+
assert_is_error!(error, AggregatorClientError::RemoteServerTechnical(_));
500+
}
501+
502+
#[tokio::test]
503+
async fn test_aggregator_features_ko_json_serialization() {
504+
let (server, client) = setup_server_and_client();
505+
set_unparsable_json(&server);
506+
507+
let error = client.retrieve_aggregator_features().await.unwrap_err();
508+
509+
assert_is_error!(error, AggregatorClientError::JsonParseFailed(_));
510+
}
511+
512+
#[tokio::test]
513+
async fn test_aggregator_features_timeout() {
514+
let (server, mut client) = setup_server_and_client();
515+
client.timeout_duration = Some(Duration::from_millis(10));
516+
let _server_mock = server.mock(|when, then| {
517+
when.path("/");
518+
then.delay(Duration::from_millis(100));
519+
});
520+
521+
let error = client.retrieve_aggregator_features().await.unwrap_err();
522+
523+
assert_is_error!(error, AggregatorClientError::RemoteServerUnreachable(_));
524+
}
415525
}
416526

417527
#[tokio::test]

0 commit comments

Comments
 (0)