Skip to content

Feat: immutable file digests route for CardanoDatabase artifacts aggregator #2204

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
1defa0b
feat: create 'immutable_file_digest' table in aggregator migration
jpraynaud Jan 6, 2025
4d17ee3
feat: implement ImmutableFileDigest record in aggregator database
jpraynaud Jan 6, 2025
9d3f464
feat: implement ImmutableFileDigest queries in aggregator database
jpraynaud Jan 6, 2025
ea920f0
feat: implement ImmutableFileDigest repository in aggregator database
jpraynaud Jan 6, 2025
0874ced
feat: implement 'ImmutableFileDigestCacheProvider' trait for 'Immutab…
jpraynaud Jan 7, 2025
080e71f
chore: wire 'ImmutableFileDigestRepository' in dependency injection
jpraynaud Jan 7, 2025
d0da189
feat: add 'ImmutableFileDigestMapper' trait in aggregator
jpraynaud Jan 7, 2025
ea0d8ed
feat: implement 'ImmutableFileDigestMapper' trait on 'ImmutableFileDi…
jpraynaud Jan 7, 2025
54925d5
feat: update OpenAPI specs
jpraynaud Jan 7, 2025
f461948
feat: implement 'CardanoDatabaseDigestListMessage' and 'CardanoDataba…
jpraynaud Jan 7, 2025
6aca881
feat: update message service to provide 'CardanoDatabaseDigestListMes…
jpraynaud Jan 7, 2025
6c195e3
feat: inject 'ImmutableFileDigestMapper' in DI builder
jpraynaud Jan 7, 2025
71512c6
feat: implement immutable digest route for Cardano database artificat…
jpraynaud Jan 7, 2025
f1bbaf6
feat: check immutable digest route produces non empty map in e2e test
jpraynaud Jan 7, 2025
9bdb444
refactor: enhance tests of 'ImmutableFileDigestRepository'
jpraynaud Jan 8, 2025
a0b1831
refactor: enhance dummy function signature of 'ImmutableFile'
jpraynaud Jan 8, 2025
de7fb4f
refactor: enhance query projection expansion in 'ImmutableFileDigestR…
jpraynaud Jan 8, 2025
e85e715
refactor: enhance e2e tests assertions
jpraynaud Jan 8, 2025
464482e
docs: update CHANGELOG
jpraynaud Jan 8, 2025
b3cb0d1
chore: upgrade crate versions and `openapi.yaml` version
jpraynaud Jan 8, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ As a minor extension, we have adopted a slightly different versioning convention
- **UNSTABLE** Cardano database incremental certification:

- Implement the artifact routes of the aggregator for the signed entity type `CardanoDatabase`.
- Implement the immutable file digests route in the aggregator.
- Implement the artifact ancillary builder in the aggregator.

- Crates versions:
Expand Down
6 changes: 3 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion mithril-aggregator/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "mithril-aggregator"
version = "0.6.9"
version = "0.6.10"
description = "A Mithril Aggregator server"
authors = { workspace = true }
edition = { workspace = true }
Expand Down
12 changes: 12 additions & 0 deletions mithril-aggregator/src/database/migration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -880,5 +880,17 @@ drop table pending_certificate;
alter table new_pending_certificate rename to pending_certificate;
"#,
),
// Migration 34
// Add the `immutable_file_digest` table.
SqlMigration::new(
34,
r#"
create table immutable_file_digest (
immutable_file_name text not null,
digest text not null,
primary key (immutable_file_name)
);
"#,
),
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
use mithril_persistence::sqlite::{Query, WhereCondition};

use crate::database::record::ImmutableFileDigestRecord;

/// Query to delete [ImmutableFileDigestRecord] from the sqlite database
pub struct DeleteImmutableFileDigestQuery {
condition: WhereCondition,
}

impl DeleteImmutableFileDigestQuery {
pub fn all() -> Self {
Self {
condition: WhereCondition::default(),
}
}
}

impl Query for DeleteImmutableFileDigestQuery {
type Entity = ImmutableFileDigestRecord;

fn filters(&self) -> WhereCondition {
self.condition.clone()
}

fn get_definition(&self, condition: &str) -> String {
let projection = Self::Entity::expand_projection("immutable_file_digest");

format!("delete from immutable_file_digest where {condition} returning {projection}")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
use sqlite::Value;

use mithril_common::{entities::ImmutableFileName, StdResult};
use mithril_persistence::sqlite::{Query, WhereCondition};

use crate::database::record::ImmutableFileDigestRecord;

/// Simple queries to retrieve [ImmutableFileDigestRecord] from the sqlite database.
pub struct GetImmutableFileDigestQuery {
condition: WhereCondition,
}

impl GetImmutableFileDigestQuery {
pub fn by_immutable_file_name(immutable_file_name: &ImmutableFileName) -> StdResult<Self> {
let condition = WhereCondition::new(
"immutable_file_name = ?*",
vec![Value::String(immutable_file_name.to_string())],
);

Ok(Self { condition })
}

pub fn all() -> Self {
Self {
condition: WhereCondition::default(),
}
}
}

impl Query for GetImmutableFileDigestQuery {
type Entity = ImmutableFileDigestRecord;

fn filters(&self) -> WhereCondition {
self.condition.clone()
}

fn get_definition(&self, condition: &str) -> String {
let projection = Self::Entity::expand_projection("immutable_file_digest");

format!(
"select {projection} from immutable_file_digest where {condition} order by rowid desc"
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
mod delete_immutable_file_digest;
mod get_immutable_file_digest;
mod upsert_immutable_file_digest;

pub use delete_immutable_file_digest::*;
pub use get_immutable_file_digest::*;
pub use upsert_immutable_file_digest::*;
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
use sqlite::Value;

use mithril_common::entities::ImmutableFileName;
use mithril_common::StdResult;
use mithril_persistence::sqlite::{Query, WhereCondition};

use crate::database::record::ImmutableFileDigestRecord;

/// Query to upsert [ImmutableFileDigestRecord] in the sqlite database
pub struct UpsertImmutableFileDigestQuery {
condition: WhereCondition,
}

impl UpsertImmutableFileDigestQuery {
pub fn one(immutable_file_name: &ImmutableFileName, digest: &str) -> StdResult<Self> {
let expression = "(immutable_file_name, digest) values (?*, ?*)";
let parameters = vec![
Value::String(immutable_file_name.to_string()),
Value::String(digest.to_string()),
];

Ok(Self {
condition: WhereCondition::new(expression, parameters),
})
}
}

impl Query for UpsertImmutableFileDigestQuery {
type Entity = ImmutableFileDigestRecord;

fn filters(&self) -> WhereCondition {
self.condition.clone()
}

fn get_definition(&self, condition: &str) -> String {
let projection = Self::Entity::expand_projection("immutable_file_digest");

format!(
r#"
insert into immutable_file_digest {condition}
on conflict (immutable_file_name) do update set digest = excluded.digest
returning {projection}
"#
)
}
}
2 changes: 2 additions & 0 deletions mithril-aggregator/src/database/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
mod buffered_single_signature;
mod certificate;
mod epoch_settings;
mod immutable_file_digest;
mod open_message;
mod pending_certificate;
mod signed_entity;
Expand All @@ -13,6 +14,7 @@ mod stake_pool;
pub use buffered_single_signature::*;
pub use certificate::*;
pub use epoch_settings::*;
pub use immutable_file_digest::*;
pub use open_message::*;
pub use pending_certificate::*;
pub use signed_entity::*;
Expand Down
57 changes: 57 additions & 0 deletions mithril-aggregator/src/database/record/immutable_file_digest.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
use sqlite::Row;

use mithril_common::entities::{HexEncodedDigest, ImmutableFileName};
use mithril_persistence::sqlite::{HydrationError, Projection, SourceAlias, SqLiteEntity};

/// ImmutableFileDigestRecord is the record that stores the digest of an immutable file.
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct ImmutableFileDigestRecord {
/// Immutable file name
pub immutable_file_name: ImmutableFileName,

/// Digest of an immutable file
pub digest: HexEncodedDigest,
}

impl ImmutableFileDigestRecord {
/// Construct a [Projection] that will allow to hydrate this `CertificatePendingRecord` and expend table alias.
pub fn expand_projection(table: &str) -> String {
let aliases = SourceAlias::new(&[("{:immutable_file_digest:}", table)]);
Self::get_projection().expand(aliases)
}

#[cfg(test)]
/// Create a dumb ImmutableFileDigestRecord instance mainly for test purposes
pub fn dummy() -> Self {
Self {
immutable_file_name: "123.chunk".to_string(),
digest: "dummy_digest".to_string(),
}
}
}

impl SqLiteEntity for ImmutableFileDigestRecord {
fn hydrate(row: Row) -> Result<Self, HydrationError>
where
Self: Sized,
{
let immutable_file_name = row.read::<&str, _>(0).to_string();
let digest = row.read::<&str, _>(1).to_string();

Ok(Self {
immutable_file_name,
digest,
})
}

fn get_projection() -> Projection {
Projection::from(&[
(
"immutable_file_name",
"{:immutable_file_digest:}.immutable_file_name",
"text",
),
("digest", "{:immutable_file_digest:}.digest", "text"),
])
}
}
2 changes: 2 additions & 0 deletions mithril-aggregator/src/database/record/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ mod buffered_single_signature_record;
mod certificate;
mod certificate_pending;
mod epoch_settings;
mod immutable_file_digest;
mod open_message;
mod open_message_with_single_signatures;
mod signed_entity;
Expand All @@ -16,6 +17,7 @@ pub use buffered_single_signature_record::*;
pub use certificate::*;
pub use certificate_pending::*;
pub use epoch_settings::*;
pub use immutable_file_digest::*;
pub use open_message::*;
pub use open_message_with_single_signatures::*;
pub use signed_entity::*;
Expand Down
Loading