Skip to content

Commit 14d1067

Browse files
committed
feature: Create digest file to upload
1 parent c98b1f2 commit 14d1067

File tree

3 files changed

+182
-29
lines changed

3 files changed

+182
-29
lines changed

Diff for: mithril-aggregator/src/artifact_builder/cardano_database.rs

+18-10
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ fn compute_uncompressed_database_size(path: &Path) -> StdResult<u64> {
122122

123123
#[cfg(test)]
124124
mod tests {
125-
use std::path::PathBuf;
125+
use std::{collections::BTreeMap, path::PathBuf};
126126

127127
use mithril_common::{
128128
digesters::DummyCardanoDbBuilder,
@@ -136,9 +136,8 @@ mod tests {
136136
use reqwest::Url;
137137

138138
use crate::{
139-
artifact_builder::{
140-
MockAncillaryFileUploader, MockDigestFileUploader, MockImmutableFilesUploader,
141-
},
139+
artifact_builder::{MockAncillaryFileUploader, MockImmutableFilesUploader},
140+
immutable_file_digest_mapper::MockImmutableFileDigestMapper,
142141
test_tools::TestLogger,
143142
DumbSnapshotter,
144143
};
@@ -231,12 +230,21 @@ mod tests {
231230
.unwrap()
232231
};
233232

234-
let digest_artifact_builder = DigestArtifactBuilder::new(
235-
Url::parse("http://aggregator_uri").unwrap(),
236-
vec![],
237-
TestLogger::stdout(),
238-
)
239-
.unwrap();
233+
let digest_artifact_builder = {
234+
let mut immutable_file_digest_mapper = MockImmutableFileDigestMapper::new();
235+
236+
immutable_file_digest_mapper
237+
.expect_get_immutable_file_digest_map()
238+
.returning(|| Ok(BTreeMap::new()));
239+
240+
DigestArtifactBuilder::new(
241+
Url::parse("http://aggregator_uri").unwrap(),
242+
vec![],
243+
Arc::new(immutable_file_digest_mapper),
244+
TestLogger::stdout(),
245+
)
246+
.unwrap()
247+
};
240248

241249
let cardano_database_artifact_builder = CardanoDatabaseArtifactBuilder::new(
242250
test_dir,

Diff for: mithril-aggregator/src/artifact_builder/cardano_database_artifacts/digest.rs

+154-18
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
11
use std::{
2+
fs,
23
path::{Path, PathBuf},
34
sync::Arc,
45
};
56

6-
use anyhow::anyhow;
7+
use anyhow::Context;
78
use async_trait::async_trait;
8-
use mithril_common::{entities::DigestLocation, logging::LoggerExtensions, StdResult};
9+
use mithril_common::{
10+
entities::DigestLocation, logging::LoggerExtensions,
11+
messages::CardanoDatabaseDigestListItemMessage, StdResult,
12+
};
913
use reqwest::Url;
10-
use slog::{debug, error, Logger};
14+
use slog::{error, Logger};
1115

12-
use crate::{file_uploaders::url_sanitizer::sanitize_url_path, snapshotter::OngoingSnapshot};
16+
use crate::ImmutableFileDigestMapper;
1317

1418
/// The [DigestFileUploader] trait allows identifying uploaders that return locations for digest archive files.
1519
#[cfg_attr(test, mockall::automock)]
@@ -24,6 +28,9 @@ pub struct DigestArtifactBuilder {
2428
aggregator_url_prefix: Url,
2529
/// Uploaders
2630
uploaders: Vec<Arc<dyn DigestFileUploader>>,
31+
32+
immutable_file_digest_mapper: Arc<dyn ImmutableFileDigestMapper>,
33+
2734
logger: Logger,
2835
}
2936

@@ -32,27 +39,60 @@ impl DigestArtifactBuilder {
3239
pub fn new(
3340
aggregator_url_prefix: Url,
3441
uploaders: Vec<Arc<dyn DigestFileUploader>>,
42+
immutable_file_digest_mapper: Arc<dyn ImmutableFileDigestMapper>,
3543
logger: Logger,
3644
) -> StdResult<Self> {
3745
Ok(Self {
3846
aggregator_url_prefix,
3947
uploaders,
48+
immutable_file_digest_mapper,
4049
logger: logger.new_with_component_name::<Self>(),
4150
})
4251
}
4352

4453
pub async fn upload(&self) -> StdResult<Vec<DigestLocation>> {
45-
// let snapshot = self.create_digest_archive(beacon)?;
46-
// let digest_path = snapshot.get_file_path();
47-
let digest_path = Path::new("");
54+
let digest_path = self.create_digest_archive().await?;
4855

49-
self.upload_digest_archive(digest_path).await
56+
let locations = self.upload_digest_archive(&digest_path).await;
57+
fs::remove_file(&digest_path).with_context(|| {
58+
format!(
59+
"Could not remove digest archive file: '{}'",
60+
digest_path.display()
61+
)
62+
})?;
63+
locations
5064
}
5165

52-
async fn create_digest_archive() -> StdResult<OngoingSnapshot> {
53-
// get message service::get_cardano_database_digest_list_message
54-
// output json (created from message) to file
55-
todo!()
66+
async fn create_digest_archive(&self) -> StdResult<PathBuf> {
67+
let immutable_file_digest_map = self
68+
.immutable_file_digest_mapper
69+
.get_immutable_file_digest_map()
70+
.await?
71+
.into_iter()
72+
.map(
73+
|(immutable_file_name, digest)| CardanoDatabaseDigestListItemMessage {
74+
immutable_file_name,
75+
digest,
76+
},
77+
)
78+
.collect::<Vec<_>>();
79+
80+
// TODO : change that injecting the path or using snapshotter
81+
let digests_file_path = Path::new("/tmp").join("mithril").join("digests.json");
82+
83+
if let Some(digests_dir) = digests_file_path.parent() {
84+
fs::create_dir_all(digests_dir).with_context(|| {
85+
format!(
86+
"Can not create digests directory: '{}'",
87+
digests_dir.display()
88+
)
89+
})?;
90+
}
91+
92+
let digest_file = fs::File::create(digests_file_path.clone()).unwrap();
93+
serde_json::to_writer(digest_file, &immutable_file_digest_map)?;
94+
95+
Ok(digests_file_path)
5696
}
5797

5898
/// Uploads the digest archive and returns the locations of the uploaded files.
@@ -94,8 +134,16 @@ impl DigestArtifactBuilder {
94134

95135
#[cfg(test)]
96136
mod tests {
97-
use crate::test_tools::TestLogger;
98-
use mithril_common::test_utils::{assert_equivalent, TempDir};
137+
use std::{collections::BTreeMap, fs::read_to_string};
138+
139+
use crate::{
140+
immutable_file_digest_mapper::MockImmutableFileDigestMapper, test_tools::TestLogger,
141+
};
142+
use anyhow::anyhow;
143+
use mithril_common::{
144+
messages::{CardanoDatabaseDigestListItemMessage, CardanoDatabaseDigestListMessage},
145+
test_utils::{assert_equivalent, TempDir},
146+
};
99147

100148
use super::*;
101149

@@ -121,9 +169,15 @@ mod tests {
121169

122170
#[tokio::test]
123171
async fn digest_artifact_builder_return_digests_route_on_aggregator() {
172+
let mut immutable_file_digest_mapper = MockImmutableFileDigestMapper::new();
173+
immutable_file_digest_mapper
174+
.expect_get_immutable_file_digest_map()
175+
.returning(|| Ok(BTreeMap::new()));
176+
124177
let builder = DigestArtifactBuilder::new(
125178
Url::parse("https://aggregator/").unwrap(),
126179
vec![],
180+
Arc::new(immutable_file_digest_mapper),
127181
TestLogger::stdout(),
128182
)
129183
.unwrap();
@@ -151,11 +205,14 @@ mod tests {
151205
let builder = DigestArtifactBuilder::new(
152206
Url::parse("https://aggregator/").unwrap(),
153207
vec![Arc::new(uploader)],
208+
Arc::new(MockImmutableFileDigestMapper::new()),
154209
TestLogger::file(&log_path),
155210
)
156211
.unwrap();
157212

158-
let _ = builder.upload_digest_archive(&Path::new("")).await;
213+
let _ = builder
214+
.upload_digest_archive(Path::new("digest_file"))
215+
.await;
159216
}
160217

161218
let logs = std::fs::read_to_string(&log_path).unwrap();
@@ -169,11 +226,15 @@ mod tests {
169226
let builder = DigestArtifactBuilder::new(
170227
Url::parse("https://aggregator/").unwrap(),
171228
vec![Arc::new(uploader)],
229+
Arc::new(MockImmutableFileDigestMapper::new()),
172230
TestLogger::stdout(),
173231
)
174232
.unwrap();
175233

176-
let locations = builder.upload_digest_archive(&Path::new("")).await.unwrap();
234+
let locations = builder
235+
.upload_digest_archive(Path::new("digest_file"))
236+
.await
237+
.unwrap();
177238

178239
assert!(!locations.is_empty());
179240
}
@@ -193,11 +254,15 @@ mod tests {
193254
let builder = DigestArtifactBuilder::new(
194255
Url::parse("https://aggregator/").unwrap(),
195256
uploaders,
257+
Arc::new(MockImmutableFileDigestMapper::new()),
196258
TestLogger::stdout(),
197259
)
198260
.unwrap();
199261

200-
let locations = builder.upload_digest_archive(&Path::new("")).await.unwrap();
262+
let locations = builder
263+
.upload_digest_archive(Path::new("digest_file"))
264+
.await
265+
.unwrap();
201266

202267
assert_equivalent(
203268
locations,
@@ -223,11 +288,15 @@ mod tests {
223288
let builder = DigestArtifactBuilder::new(
224289
Url::parse("https://aggregator/").unwrap(),
225290
uploaders,
291+
Arc::new(MockImmutableFileDigestMapper::new()),
226292
TestLogger::stdout(),
227293
)
228294
.unwrap();
229295

230-
let locations = builder.upload_digest_archive(&Path::new("")).await.unwrap();
296+
let locations = builder
297+
.upload_digest_archive(Path::new("digest_file"))
298+
.await
299+
.unwrap();
231300

232301
assert_equivalent(
233302
locations,
@@ -244,4 +313,71 @@ mod tests {
244313
],
245314
);
246315
}
316+
317+
#[tokio::test]
318+
async fn create_digest_archive_should_create_json_file_with_all_digests() {
319+
let mut immutable_file_digest_mapper = MockImmutableFileDigestMapper::new();
320+
immutable_file_digest_mapper
321+
.expect_get_immutable_file_digest_map()
322+
.returning(|| {
323+
Ok(BTreeMap::from([(
324+
"06685.chunk".to_string(),
325+
"0af556ab2620dd9363bf76963a231abe8948a500ea6be31b131d87907ab09b1e".to_string(),
326+
)]))
327+
});
328+
329+
let builder = DigestArtifactBuilder::new(
330+
Url::parse("https://aggregator/").unwrap(),
331+
vec![],
332+
Arc::new(immutable_file_digest_mapper),
333+
TestLogger::stdout(),
334+
)
335+
.unwrap();
336+
337+
let archive_path = builder.create_digest_archive().await.unwrap();
338+
let file_content = read_to_string(archive_path).unwrap();
339+
let digest_content: CardanoDatabaseDigestListMessage =
340+
serde_json::from_str(&file_content).unwrap();
341+
342+
assert_eq!(
343+
digest_content,
344+
vec![CardanoDatabaseDigestListItemMessage {
345+
immutable_file_name: "06685.chunk".to_string(),
346+
digest: "0af556ab2620dd9363bf76963a231abe8948a500ea6be31b131d87907ab09b1e"
347+
.to_string(),
348+
}]
349+
);
350+
}
351+
352+
#[tokio::test]
353+
async fn upload_should_call_upload_with_created_digest_file_and_delete_the_file() {
354+
// TODO : This test is flaky because we create and remove a file with an hard coded path
355+
let mut immutable_file_digest_mapper = MockImmutableFileDigestMapper::new();
356+
immutable_file_digest_mapper
357+
.expect_get_immutable_file_digest_map()
358+
.returning(|| Ok(BTreeMap::new()));
359+
360+
let mut digest_file_uploader = MockDigestFileUploader::new();
361+
digest_file_uploader
362+
.expect_upload()
363+
.withf(|path| path == Path::new("/tmp/mithril/digests.json") && path.exists())
364+
.times(1)
365+
.return_once(|_| {
366+
Ok(DigestLocation::CloudStorage {
367+
uri: "an_uri".to_string(),
368+
})
369+
});
370+
371+
let builder = DigestArtifactBuilder::new(
372+
Url::parse("https://aggregator/").unwrap(),
373+
vec![Arc::new(digest_file_uploader)],
374+
Arc::new(immutable_file_digest_mapper),
375+
TestLogger::stdout(),
376+
)
377+
.unwrap();
378+
379+
let _locations = builder.upload().await.unwrap();
380+
381+
assert!(!Path::new("/tmp/mithril/digests.json").exists());
382+
}
247383
}

Diff for: mithril-aggregator/src/dependency_injection/builder.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -1230,6 +1230,7 @@ impl DependenciesBuilder {
12301230
logger: &Logger,
12311231
cardano_node_version: Version,
12321232
snapshotter: Arc<dyn Snapshotter>,
1233+
immutable_file_digest_mapper: Arc<dyn ImmutableFileDigestMapper>,
12331234
) -> Result<CardanoDatabaseArtifactBuilder> {
12341235
let artifacts_dir = Path::new("cardano-database").join("ancillary");
12351236
let snapshot_dir = self
@@ -1265,6 +1266,7 @@ impl DependenciesBuilder {
12651266
let digest_builder = Arc::new(DigestArtifactBuilder::new(
12661267
self.get_server_url_prefix()?,
12671268
vec![],
1269+
immutable_file_digest_mapper,
12681270
logger.clone(),
12691271
)?);
12701272

@@ -1305,11 +1307,13 @@ impl DependenciesBuilder {
13051307
let stake_store = self.get_stake_store().await?;
13061308
let cardano_stake_distribution_artifact_builder =
13071309
Arc::new(CardanoStakeDistributionArtifactBuilder::new(stake_store));
1310+
let immutable_file_digest_mapper = self.get_immutable_file_digest_mapper().await?;
13081311
let cardano_database_artifact_builder =
13091312
Arc::new(self.create_cardano_database_artifact_builder(
13101313
&logger,
13111314
cardano_node_version,
13121315
snapshotter,
1316+
immutable_file_digest_mapper,
13131317
)?);
13141318
let dependencies = SignedEntityServiceArtifactsDependencies::new(
13151319
mithril_stake_distribution_artifact_builder,
@@ -1825,7 +1829,9 @@ impl DependenciesBuilder {
18251829
mod tests {
18261830
use mithril_common::{entities::SignedEntityTypeDiscriminants, test_utils::TempDir};
18271831

1828-
use crate::test_tools::TestLogger;
1832+
use crate::{
1833+
immutable_file_digest_mapper::MockImmutableFileDigestMapper, test_tools::TestLogger,
1834+
};
18291835

18301836
use super::*;
18311837

@@ -1888,11 +1894,14 @@ mod tests {
18881894

18891895
assert!(!ancillary_dir.exists());
18901896

1897+
let immutable_file_digest_mapper = MockImmutableFileDigestMapper::new();
1898+
18911899
dep_builder
18921900
.create_cardano_database_artifact_builder(
18931901
&TestLogger::stdout(),
18941902
Version::parse("1.0.0").unwrap(),
18951903
Arc::new(DumbSnapshotter::new()),
1904+
Arc::new(immutable_file_digest_mapper),
18961905
)
18971906
.unwrap();
18981907

0 commit comments

Comments
 (0)