Skip to content

Commit 19e0a35

Browse files
committed
add default version for the DB
1 parent 46c051a commit 19e0a35

File tree

3 files changed

+79
-33
lines changed

3 files changed

+79
-33
lines changed

mithril-aggregator/src/command_args.rs

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,7 @@ fn setup_genesis_dependencies(
3737
config: &GenesisConfiguration,
3838
) -> Result<GenesisToolsDependency, Box<dyn std::error::Error>> {
3939
let sqlite_db_path = Some(config.get_sqlite_file());
40-
DatabaseVersionChecker::new(
41-
slog_scope::logger(),
42-
ApplicationNodeType::Aggregator,
43-
config.get_sqlite_file(),
44-
)
45-
.apply()?;
40+
check_database_migration(config.get_sqlite_file())?;
4641

4742
let chain_observer = Arc::new(
4843
mithril_common::chain_observer::CardanoCliChainObserver::new(Box::new(
@@ -143,6 +138,17 @@ async fn do_first_launch_initialization_if_needed(
143138
Ok(())
144139
}
145140

141+
/// Database version checker.
142+
/// This is the place where migrations are to be registered.
143+
fn check_database_migration(sql_file_path: PathBuf) -> Result<(), Box<dyn Error>> {
144+
DatabaseVersionChecker::new(
145+
slog_scope::logger(),
146+
ApplicationNodeType::Aggregator,
147+
sql_file_path,
148+
)
149+
.apply()
150+
}
151+
146152
/// Mithril Aggregator Node
147153
#[derive(Parser, Debug, Clone)]
148154
#[command(version)]
@@ -304,12 +310,7 @@ impl ServeCommand {
304310
.map_err(|e| format!("configuration deserialize error: {}", e))?;
305311
debug!("SERVE command"; "config" => format!("{:?}", config));
306312
let sqlite_db_path = Some(config.get_sqlite_file());
307-
DatabaseVersionChecker::new(
308-
slog_scope::logger(),
309-
ApplicationNodeType::Aggregator,
310-
config.get_sqlite_file(),
311-
)
312-
.apply()?;
313+
check_database_migration(config.get_sqlite_file())?;
313314

314315
// Init dependencies
315316
let snapshot_store = config.build_snapshot_store()?;

mithril-common/src/database/db_version.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,10 @@ impl<'conn> DatabaseVersionProvider<'conn> {
127127

128128
/// Method to create the table at the beginning of the migration procedure.
129129
/// This code is temporary and should not last.
130-
pub fn create_table_if_not_exists(&self) -> Result<(), Box<dyn Error>> {
130+
pub fn create_table_if_not_exists(
131+
&self,
132+
application_type: &ApplicationNodeType,
133+
) -> Result<(), Box<dyn Error>> {
131134
let connection = self.get_connection();
132135
let sql = "select exists(select name from sqlite_master where type='table' and name='db_version') as table_exists";
133136
let table_exists = connection
@@ -140,9 +143,10 @@ impl<'conn> DatabaseVersionProvider<'conn> {
140143
== 1;
141144

142145
if !table_exists {
143-
let sql = r#"
144-
create table db_version (application_type text not null primary key, version integer not null, updated_at timestamp not null default CURRENT_TIMESTAMP)
145-
"#;
146+
let sql = format!("
147+
create table db_version (application_type text not null primary key, version integer not null, updated_at timestamp not null default CURRENT_TIMESTAMP);
148+
insert into db_version (application_type, version) values ('{application_type}', 0);
149+
");
146150
connection.execute(sql)?;
147151
}
148152

mithril-common/src/database/version_checker.rs

Lines changed: 58 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -59,15 +59,13 @@ impl DatabaseVersionChecker {
5959
);
6060
let connection = Connection::open(&self.sqlite_file_path)?;
6161
let provider = DatabaseVersionProvider::new(&connection);
62-
provider.create_table_if_not_exists()?;
62+
provider.create_table_if_not_exists(&self.application_type)?;
6363
let updater = DatabaseVersionUpdater::new(&connection);
6464
let db_version = provider
6565
.get_application_version(&self.application_type)?
66-
.unwrap_or_else(|| DatabaseVersion {
67-
version: 0,
68-
application_type: self.application_type.clone(),
69-
updated_at: Local::now().naive_local(),
70-
});
66+
.unwrap(); // At least a record exists.
67+
68+
// if no migration registered then we are at version 0.
7169
let migration_version = self.migrations.iter().map(|m| m.version).max().unwrap_or(0);
7270

7371
match migration_version.cmp(&db_version.version) {
@@ -176,17 +174,15 @@ mod tests {
176174
let version = provider
177175
.get_application_version(&ApplicationNodeType::Aggregator)
178176
.unwrap()
179-
.unwrap_or_else(|| DatabaseVersion {
180-
application_type: ApplicationNodeType::Aggregator,
181-
version: 0,
182-
updated_at: Local::now().naive_local(),
183-
});
177+
.unwrap();
184178

185179
assert_eq!(db_version, version.version);
186180
}
187181

188182
fn create_sqlite_file(name: &str) -> PathBuf {
189-
let filepath = std::env::temp_dir().join(name);
183+
let dirpath = std::env::temp_dir().join("mithril_test_database");
184+
std::fs::create_dir_all(&dirpath).unwrap();
185+
let filepath = dirpath.join(name);
190186

191187
if filepath.exists() {
192188
std::fs::remove_file(filepath.as_path()).unwrap();
@@ -214,7 +210,7 @@ mod tests {
214210

215211
#[test]
216212
fn test_upgrade_with_migration() {
217-
let filepath = create_sqlite_file("test_1.sqlite3");
213+
let filepath = create_sqlite_file("test_upgrade_with_migration.sqlite3");
218214
let mut db_checker = DatabaseVersionChecker::new(
219215
slog_scope::logger(),
220216
ApplicationNodeType::Aggregator,
@@ -273,7 +269,7 @@ mod tests {
273269

274270
#[test]
275271
fn starting_with_migration() {
276-
let filepath = create_sqlite_file("test_2.sqlite3");
272+
let filepath = create_sqlite_file("starting_with_migration.sqlite3");
277273
let mut db_checker = DatabaseVersionChecker::new(
278274
slog_scope::logger(),
279275
ApplicationNodeType::Aggregator,
@@ -292,21 +288,66 @@ mod tests {
292288
}
293289

294290
#[test]
291+
/// This test case ensure that when multiple migrations are played and one fails:
292+
/// * previous migrations are ok and the database version is updated
293+
/// * further migrations are not played.
295294
fn test_failing_migration() {
296-
let filepath = create_sqlite_file("test_3.sqlite3");
295+
let filepath = create_sqlite_file("test_failing_migration.sqlite3");
297296
let mut db_checker = DatabaseVersionChecker::new(
298297
slog_scope::logger(),
299298
ApplicationNodeType::Aggregator,
300299
filepath.clone(),
301300
);
302301
// Table whatever does not exist, this should fail with error.
303-
let alterations = "alter table whatever add column thing_content text; update whatever set thing_content = 'some content'";
302+
let alterations = "create table whatever (thing_id integer); insert into whatever (thing_id) values (1), (2), (3), (4);";
304303
let migration = SqlMigration {
305304
version: 1,
306305
alterations: alterations.to_string(),
307306
};
308307
db_checker.add_migration(migration);
308+
let alterations = "alter table wrong add column thing_content text; update whatever set thing_content = 'some content'";
309+
let migration = SqlMigration {
310+
version: 2,
311+
alterations: alterations.to_string(),
312+
};
313+
db_checker.add_migration(migration);
314+
let alterations = "alter table whatever add column thing_content text; update whatever set thing_content = 'some content'";
315+
let migration = SqlMigration {
316+
version: 3,
317+
alterations: alterations.to_string(),
318+
};
319+
db_checker.add_migration(migration);
309320
db_checker.apply().unwrap_err();
310-
check_database_version(&filepath, 0);
321+
check_database_version(&filepath, 1);
322+
}
323+
324+
#[test]
325+
fn test_fail_downgrading() {
326+
let filepath = create_sqlite_file("test_fail_downgrading.sqlite3");
327+
let mut db_checker = DatabaseVersionChecker::new(
328+
slog_scope::logger(),
329+
ApplicationNodeType::Aggregator,
330+
filepath.clone(),
331+
);
332+
let alterations = "create table whatever (thing_id integer); insert into whatever (thing_id) values (1), (2), (3), (4);";
333+
let migration = SqlMigration {
334+
version: 1,
335+
alterations: alterations.to_string(),
336+
};
337+
db_checker.add_migration(migration);
338+
db_checker.apply().unwrap();
339+
check_database_version(&filepath, 1);
340+
341+
// re instanciate a new checker with no migration registered (version 0).
342+
let db_checker = DatabaseVersionChecker::new(
343+
slog_scope::logger(),
344+
ApplicationNodeType::Aggregator,
345+
filepath.clone(),
346+
);
347+
assert!(
348+
db_checker.apply().is_err(),
349+
"using an old version with an up to date database should fail"
350+
);
351+
check_database_version(&filepath, 1);
311352
}
312353
}

0 commit comments

Comments
 (0)