Clean up interface to Program::perform_task()

This commit is contained in:
Jacob Hinkle 2022-10-27 15:23:13 -04:00
parent 88dd2bc220
commit feab22026d
4 changed files with 69 additions and 34 deletions

View File

@ -15,7 +15,7 @@ use uuid;
use std::collections::{HashSet}; use std::collections::{HashSet};
use std::num::NonZeroUsize; // for describing schema versions use std::num::NonZeroUsize; // for describing schema versions
use std::path::{Components, Path, PathBuf}; use std::path::{PathBuf};
static MIGRATIONS: Lazy<Migrations<'static>> = Lazy::new(|| { static MIGRATIONS: Lazy<Migrations<'static>> = Lazy::new(|| {
Migrations::new(vec![M::up(include_str!( Migrations::new(vec![M::up(include_str!(
@ -77,13 +77,8 @@ pub struct SchemaUpdateResult {
pub updated: bool, pub updated: bool,
} }
/// Ensure that the schema in conn is current. /// Ensure that the schema in conn is current.
///
/// If migrate is true, migrate the schema and return.
///
/// If migrate is false, throw an Error if schema is not current.
pub fn ensure_schema( pub fn ensure_schema(
conn: &mut Connection, conn: &mut Connection,
migrate: bool,
) -> Result<SchemaUpdateResult, SchemaError> { ) -> Result<SchemaUpdateResult, SchemaError> {
let old_version = schema_version(conn)?; let old_version = schema_version(conn)?;
let current_version = unsafe { NonZeroUsize::new_unchecked(CURRENT_SCHEMA_VERSION) }; let current_version = unsafe { NonZeroUsize::new_unchecked(CURRENT_SCHEMA_VERSION) };

View File

@ -1,6 +1,6 @@
//use jwalk; //use jwalk;
use log; use log;
use sha2::{digest::FixedOutput, Digest, Sha256}; //use sha2::{digest::FixedOutput, Digest, Sha256};
use std::path::Path; use std::path::Path;
#[derive(Debug)] #[derive(Debug)]
@ -9,6 +9,6 @@ pub enum RecordError {
} }
pub fn record(path: &Path, message: &String) -> Result<(), RecordError> { pub fn record(path: &Path, message: &String) -> Result<(), RecordError> {
log::info!("Recording path {:?} using message \"{}\"", path, message); log::info!("Recording path {:?} with user-provided message \"{}\"", path, message);
Err(RecordError::NotImplemented) Err(RecordError::NotImplemented)
} }

View File

@ -61,13 +61,19 @@ fn main() {
// Determine dataset dir (ds_dir) // Determine dataset dir (ds_dir)
let mut conn = match nancy::db::find_dataset_dir(record_paths) { let mut conn = match nancy::db::find_dataset_dir(record_paths) {
Err(nancy::db::FindDatasetError::NoDataset(path)) => { Err(nancy::db::FindDatasetError::NoDataset(path)) => {
// initialize
log::info!("No dataset at or above nearest ancestor path: {:?}", path); log::info!("No dataset at or above nearest ancestor path: {:?}", path);
if !initialize {
log::error!("Refusing to initialize a new dataset at {path:?}. \
Pass the -i or --initialize flag to request initialization.");
process::exit(1);
}
let dbpath = &path.join("nancy.db"); let dbpath = &path.join("nancy.db");
log::info!("Initializing new database at {:?}", dbpath);
let mut c = match Connection::open(dbpath) { let mut c = match Connection::open(dbpath) {
Err(e) => { Err(e) => {
log::error!( log::error!(
"Could not open new SQLite database at {dbpath:?}." "Could not open new SQLite database at {dbpath:?}: {:?}",
e
); );
process::exit(1); process::exit(1);
} }
@ -91,7 +97,10 @@ fn main() {
&mut c, &mut c,
"INIT", "INIT",
"Initialize dataset", "Initialize dataset",
|_| { |prog| {
let _ = prog.perform_task(&[], |task| {
log::debug!("INIT task UUID is {}", task.uuid);
});
let okres: Result<(), ()> = Ok(()); let okres: Result<(), ()> = Ok(());
okres okres
}, },
@ -123,7 +132,7 @@ fn main() {
Ok(cc) => cc, Ok(cc) => cc,
}; };
c.pragma_update(None, "foreign_keys", &"ON").unwrap(); c.pragma_update(None, "foreign_keys", &"ON").unwrap();
match nancy::db::ensure_schema(&mut c, true) { match nancy::db::ensure_schema(&mut c) {
Err(e) => { Err(e) => {
log::error!("Error ensuring schema: {}", e); log::error!("Error ensuring schema: {}", e);
process::exit(1); process::exit(1);
@ -137,10 +146,12 @@ fn main() {
}; };
if let Err(e) = nancy::program::with_program(&mut conn, "RECORD", message, |prog| { if let Err(e) = nancy::program::with_program(&mut conn, "RECORD", message, |prog| {
prog.perform_task(&[], |_task| {
let dataset_path = PathBuf::from("."); let dataset_path = PathBuf::from(".");
// Note that this may fail, in which case we should roll back only this program // Note that this may fail, in which case we should roll back only this program
// but keep the dataset initialized. // but keep the dataset initialized.
nancy::fs::record(&dataset_path, message) nancy::fs::record(&dataset_path, message)
})
}) { }) {
log::error!("Encountered error in RECORD program: {:?}", e); log::error!("Encountered error in RECORD program: {:?}", e);
process::exit(1); process::exit(1);

View File

@ -1,31 +1,57 @@
use log; use log;
use rusqlite::{Connection, Error as RSQLError}; use rusqlite::{Connection, Error as RSQLError, Transaction};
extern crate derive_more; extern crate derive_more;
use derive_more::From; use derive_more::From;
use uuid::{Uuid};
use std::time::{Instant, SystemTime}; use std::time::{Instant, SystemTime};
use crate::timing; use crate::timing;
#[derive(Debug)]
pub struct Task { pub struct Task {
start: Instant, pub uuid: Uuid,
end: Option<Instant>, pub start: Instant,
uuid: String, pub end: Instant,
} }
pub struct TaskInput<T> { #[derive(Debug)]
task: Task, pub struct TaskInput {
datum: T, pub task: Task,
//datum: data::Datum,
} }
pub struct Program {} #[derive(Debug)]
pub struct Program {
pub uuid: Uuid,
pub name: String,
pub message: String,
}
impl Program { impl Program {
//fn new(conn: &Connection) -> Self { pub fn new(tx: &mut Transaction, name: &str, message: &str) -> Program {
//Program { let u = Uuid::new_v4();
//} log::debug!("New {} Program with UUID {}", name, u);
//} Program {
//fn new_task(self: &Program) -> Task { uuid: u,
//} name: name.to_string(),
message: message.to_string(),
}
}
pub fn perform_task<R, F>(self: &Program, inputs: &[TaskInput], f: F) -> R
where
F: FnOnce(&Task) -> R
{
let start = Instant::now();
let u = Uuid::new_v4();
let mut task = Task {
uuid: u,
start: start,
end: start,
};
let res = f(&task);
task.end = Instant::now();
res
}
} }
#[derive(Debug)] #[derive(Debug)]
@ -53,12 +79,13 @@ pub fn with_program<E, F: FnOnce(Program) -> Result<(), E>>(
let log_target = &format!("nancy.program ({})", name); let log_target = &format!("nancy.program ({})", name);
log::info!(target: log_target, "Running program {} ({})", name, message); log::info!(target: log_target, "Preparing program {} ({})", name, message);
// start transaction // start transaction
match conn.transaction() { let txres = conn.transaction();
match txres {
Err(e) => Err(ProgramError::CreateTransactionFailed(e)), Err(e) => Err(ProgramError::CreateTransactionFailed(e)),
Ok(tx) => { Ok(mut tx) => {
// start timer // start timer
log::debug!(target: log_target, "Starting timers"); log::debug!(target: log_target, "Starting timers");
let start_st = SystemTime::now(); let start_st = SystemTime::now();
@ -67,7 +94,9 @@ pub fn with_program<E, F: FnOnce(Program) -> Result<(), E>>(
// Instantiate Program // Instantiate Program
// (record name and message for new program, get program ID) // (record name and message for new program, get program ID)
let prog = Program {}; let prog = Program::new(&mut tx, name, message);
log::info!(target: log_target, "Running {:?}", prog);
// run closure with program argument // run closure with program argument
f(prog)?; // if closure fails, transaction will be rolled back f(prog)?; // if closure fails, transaction will be rolled back