Skip to content

Commit

Permalink
start refactoring db access into dal struct
Browse files Browse the repository at this point in the history
  • Loading branch information
joshtenorio committed Dec 16, 2024
1 parent 00a8e97 commit ae00d22
Show file tree
Hide file tree
Showing 7 changed files with 185 additions and 146 deletions.
11 changes: 7 additions & 4 deletions src-tauri/src/config.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{types::SettingsOptions, dal::get_active_server};
use crate::{dal::DataAccessLayer, types::SettingsOptions};
use fs_extra::dir::{move_dir, CopyOptions};
use sqlx::{Pool, Row, Sqlite};
use tauri::State;
Expand Down Expand Up @@ -137,6 +137,7 @@ pub async fn set_local_dir(
log::info!("setting local directory to {}", dir);
log::info!("parent dir: {}", parent_dir);
let pool = state_mutex.lock().await;
let dal = DataAccessLayer::new(&pool);
let old_server_dir = get_server_dir(&pool).await.unwrap();
let _ = sqlx::query("UPDATE server SET local_dir = ? WHERE active = 1")
.bind(dir.clone())
Expand All @@ -155,7 +156,7 @@ pub async fn set_local_dir(
}
}
}
let url = get_active_server(&pool).await.unwrap();
let url = dal.get_active_server().await.unwrap();
if url == "" {
log::warn!("could not obtain active server url");
return Ok(false);
Expand All @@ -182,7 +183,8 @@ pub async fn cmd_get_cache_setting(state_mutex: State<'_, Mutex<Pool<Sqlite>>>)
#[tauri::command]
pub async fn cmd_set_cache_setting(new_cache: bool, state_mutex: State<'_, Mutex<Pool<Sqlite>>>) -> Result<bool, ()> {
let pool = state_mutex.lock().await;
let url = get_active_server(&pool).await.unwrap();
let dal = DataAccessLayer::new(&pool);
let url = dal.get_active_server().await.unwrap();

match sqlx::query("UPDATE server SET cache_setting = $1 WHERE url = $2")
.bind(if new_cache { 1 } else { 0 })
Expand All @@ -200,7 +202,8 @@ pub async fn cmd_set_cache_setting(new_cache: bool, state_mutex: State<'_, Mutex
}

pub async fn get_cache_setting(pool: &Pool<Sqlite>) -> Result<bool, ()> {
let url = get_active_server(pool).await.unwrap();
let dal = DataAccessLayer::new(pool);
let url = dal.get_active_server().await.unwrap();
match sqlx::query("SELECT cache_setting FROM server WHERE url = $1")
.bind(url)
.fetch_one(pool)
Expand Down
250 changes: 133 additions & 117 deletions src-tauri/src/dal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,138 +3,154 @@ use std::path::Path;
use std::result::Result::Ok;
use crate::types::{ChangeType, UpdatedFile};

pub async fn get_current_server(pool: &Pool<Sqlite>) -> Result<String, ()> {
let output = sqlx::query("SELECT CASE WHEN debug_active = 1 THEN debug_url ELSE url END as url FROM server WHERE active = 1").fetch_one(&*pool).await;
pub struct DataAccessLayer<'a> {
pub pool: &'a Pool<Sqlite>
}

match output {
Ok(row) => Ok(row.get::<String, &str>("url")),
Err(err) => {
log::error!("couldn't get the current server url: {}", err);
Ok("".to_string())
}
impl<'a> DataAccessLayer<'a> {
pub fn new(user_pool: &'a Pool<Sqlite>) -> Self {
DataAccessLayer { pool: &user_pool }
}
}

pub async fn get_active_server(pool: &Pool<Sqlite>) -> Result<String, ()> {
let output = sqlx::query("SELECT url FROM server WHERE active = 1")
.fetch_one(&*pool)
.await;
/// gets the current server URL to use for network calls
pub async fn get_current_server(&self) -> Result<String, ()> {
let output = sqlx::query("SELECT CASE WHEN debug_active = 1 THEN debug_url ELSE url END as url FROM server WHERE active = 1")
.fetch_one(self.pool).await;

match output {
Ok(row) => Ok(row.get::<String, &str>("url")),
Err(err) => {
log::error!("couldn't get the current server url: {}", err);
Ok("".to_string())
}
}
}

match output {
Ok(row) => Ok(row.get::<String, &str>("url")),
Err(err) => {
log::error!("couldn't get the active server url: {}", err);
Ok("".to_string())
/// gets the current server URL for db foreign key purposes
pub async fn get_active_server(&self) -> Result<String, ()> {
let output = sqlx::query("SELECT url FROM server WHERE active = 1")
.fetch_one(self.pool)
.await;

match output {
Ok(row) => Ok(row.get::<String, &str>("url")),
Err(err) => {
log::error!("couldn't get the active server url: {}", err);
Ok("".to_string())
}
}
}
}

pub async fn get_project_dir(pid: i32, pool: &Pool<Sqlite>) -> Result<String, ()> {
//println!("current allocating {}B", get_allocated());
let server = get_active_server(pool).await.unwrap();
let db_call = sqlx::query("SELECT server.local_dir, project.title, project.team_name FROM server, project WHERE server.active = 1 AND project.url = ? AND project.pid = ?")
.bind(server)
/// deletes an entry from the file table
pub async fn delete_file_entry(&self, pid: i32, path: String) -> Result<bool, ()> {
let _ = sqlx::query(
"DELETE FROM file
WHERE pid = $1 AND filepath = $2",
)
.bind(pid)
.fetch_one(pool)
.bind(path)
.execute(self.pool)
.await;
match db_call {
Ok(row) => {
let output = Path::new(&row.get::<String, &str>("local_dir"))
.join(row.get::<String, &str>("team_name"))
.join(row.get::<String, &str>("title"));
Ok(output.display().to_string())
}
Err(err) => {
log::error!("couldn't get the project directory for pid {}: {}", pid, err);
Ok("".to_string())
}
Ok(true)
}
}

pub async fn get_file_info(pid: i32, path: String, pool: &Pool<Sqlite>) -> Result<UpdatedFile, ()> {
let output = sqlx::query(
"SELECT curr_hash, size, change_type, in_fs FROM file WHERE filepath = $1 AND pid = $2",
)
.bind(path.clone())
.bind(pid)
.fetch_one(&*pool)
.await;

match output {
Ok(row) => {
let change = match row.get::<i32, &str>("change_type") {
1 => ChangeType::Create,
2 => ChangeType::Update,
3 => ChangeType::Delete,
_ => ChangeType::NoChange,
};
let in_fs = if row.get::<i32, &str>("in_fs") > 0 { true } else { false };
let owo: UpdatedFile = UpdatedFile {
path: path,
hash: row.get::<String, &str>("curr_hash").to_string(),
size: row.get::<i64, &str>("size"),
change: change,
in_fs: in_fs
};

Ok(owo)
}
Err(err) => {
log::error!("couldn't get the file information for {} in project {}: {}", path, pid, err);
Err(())
/// get the project directory for the specified project
pub async fn get_project_dir(&self, pid: i32) -> Result<String, ()> {
//println!("current allocating {}B", get_allocated());
let server = self.get_active_server().await.unwrap();
let db_call = sqlx::query("SELECT server.local_dir, project.title, project.team_name FROM server, project WHERE server.active = 1 AND project.url = ? AND project.pid = ?")
.bind(server)
.bind(pid)
.fetch_one(self.pool)
.await;
match db_call {
Ok(row) => {
let output = Path::new(&row.get::<String, &str>("local_dir"))
.join(row.get::<String, &str>("team_name"))
.join(row.get::<String, &str>("title"));
Ok(output.display().to_string())
}
Err(err) => {
log::error!("couldn't get the project directory for pid {}: {}", pid, err);
Ok("".to_string())
}
}
}
}

pub async fn get_basehash(pid: i32, path: String, pool: &Pool<Sqlite>) -> Result<String, ()> {
let result = sqlx::query(
"SELECT base_hash FROM file WHERE
pid = $1 AND filepath = $2 LIMIT 1
",
)
.bind(pid)
.bind(path)
.fetch_one(pool)
.await;

match result {
Ok(row) => Ok(row.get::<String, &str>("base_hash")),
Err(err) => {
log::error!("could not get base_hash: {}", err);
Err(())
pub async fn get_file_info(&self, pid: i32, path: String) -> Result<UpdatedFile, ()> {
let output = sqlx::query(
"SELECT curr_hash, size, change_type, in_fs FROM file WHERE filepath = $1 AND pid = $2",
)
.bind(path.clone())
.bind(pid)
.fetch_one(self.pool)
.await;

match output {
Ok(row) => {
let change = match row.get::<i32, &str>("change_type") {
1 => ChangeType::Create,
2 => ChangeType::Update,
3 => ChangeType::Delete,
_ => ChangeType::NoChange,
};
let in_fs = if row.get::<i32, &str>("in_fs") > 0 { true } else { false };
let owo: UpdatedFile = UpdatedFile {
path: path,
hash: row.get::<String, &str>("curr_hash").to_string(),
size: row.get::<i64, &str>("size"),
change: change,
in_fs: in_fs
};

Ok(owo)
}
Err(err) => {
log::error!("couldn't get the file information for {} in project {}: {}", path, pid, err);
Err(())
}
}
}
}

pub async fn delete_file_entry(pid: i32, path: String, pool: &Pool<Sqlite>) -> Result<bool, ()> {
let _ = sqlx::query(
"DELETE FROM file
WHERE pid = $1 AND filepath = $2",
)
.bind(pid)
.bind(path)
.execute(pool)
.await;
Ok(true)
}
pub async fn get_basehash(&self, pid: i32, path: String) -> Result<String, ()> {
let result = sqlx::query(
"SELECT base_hash FROM file WHERE
pid = $1 AND filepath = $2 LIMIT 1
",
)
.bind(pid)
.bind(path)
.fetch_one(self.pool)
.await;

match result {
Ok(row) => Ok(row.get::<String, &str>("base_hash")),
Err(err) => {
log::error!("could not get base_hash: {}", err);
Err(())
}
}
}

// TODO necessary to have in dal?
pub async fn update_file_entry(&self, pid: i32, path: String) -> Result<bool, ()> {
let _ = sqlx::query(
"
UPDATE file SET
base_hash = tracked_hash,
curr_hash = tracked_hash,
base_commitid = tracked_commitid,
size = tracked_size,
in_fs = 1,
change_type = 0
WHERE pid = $1 AND filepath = $2
",
)
.bind(pid)
.bind(path)
.execute(self.pool)
.await;
Ok(true)
}
} // end impl DataAcessLayer<'_>

// TODO necessary?
pub async fn update_file_entry(pid: i32, path: String, pool: &Pool<Sqlite>) -> Result<bool, ()> {
let _ = sqlx::query(
"
UPDATE file SET
base_hash = tracked_hash,
curr_hash = tracked_hash,
base_commitid = tracked_commitid,
size = tracked_size,
in_fs = 1,
change_type = 0
WHERE pid = $1 AND filepath = $2
",
)
.bind(pid)
.bind(path)
.execute(pool)
.await;
Ok(true)
}
24 changes: 18 additions & 6 deletions src-tauri/src/download.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::types::{
ReqwestError,
};
use crate::util::{delete_cache, delete_trash, get_cache_dir, get_trash_dir};
use crate::dal::{delete_file_entry, get_current_server, get_project_dir};
use crate::dal::DataAccessLayer;
use futures::{stream, StreamExt};
use log::{info, trace, warn};
use reqwest::Client;
Expand All @@ -32,8 +32,10 @@ pub async fn download_files(
app_handle: AppHandle,
) -> Result<bool, ReqwestError> {
let pool = state_mutex.lock().await;
let server_url = get_current_server(&pool).await.unwrap();
let project_dir = get_project_dir(pid, &pool).await.unwrap();
let dal = DataAccessLayer::new(&pool);

let server_url = dal.get_current_server().await.unwrap();
let project_dir = dal.get_project_dir(pid).await.unwrap();
let cache_dir = get_cache_dir(&pool).await.unwrap();
let trash_dir = get_trash_dir(&pool).await.unwrap();

Expand Down Expand Up @@ -276,7 +278,7 @@ pub async fn download_files(
.await;
} else {
// file.download == delete
let _ = delete_file_entry(pid, file.rel_path, &pool).await;
let _ = dal.delete_file_entry(pid, file.rel_path).await;
}
}

Expand Down Expand Up @@ -471,7 +473,16 @@ fn read_mapping(hash_dir: &String) -> Result<Vec<FileChunk>, ()> {

// assumes trash dir exists
pub fn trash_file(proj_dir: &String, trash_dir: &String, hash: String) -> Result<bool, ()> {
let trash_path = trash_dir.to_owned() + &(sep().to_string()) + hash.as_str();
let trash_path;
#[cfg(target_os = "windows")]
{
trash_path = trash_dir.to_owned() + &(sep().to_string()) + hash.as_str();
}
#[cfg(target_os = "linux")]
{
trash_path = translate_filepath(&(trash_dir.to_owned() + &(sep().to_string()) + hash.as_str()), true);
}

match fs::rename(proj_dir, trash_path) {
Ok(_) => Ok(true),
Err(err) => {
Expand All @@ -495,7 +506,8 @@ pub fn recover_file(trash_dir: &String, proj_dir: &String) -> Result<bool, ()> {
#[tauri::command]
pub async fn download_single_file(pid: i64, path: String, commit_id: i64, user_id: String, download_path: String, state_mutex: State<'_, Mutex<Pool<Sqlite>>>) -> Result<bool, ()> {
let pool = state_mutex.lock().await;
let server_url = get_current_server(&pool).await.unwrap();
let dal = DataAccessLayer::new(&pool);
let server_url = dal.get_current_server().await.unwrap();
let cache_dir = get_cache_dir(&pool).await.unwrap();

// request download links from glassy server
Expand Down
Loading

0 comments on commit ae00d22

Please sign in to comment.