mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-03-23 09:51:28 +01:00
Fix up DB creation and migration
This commit is contained in:
2
src-tauri/Cargo.lock
generated
2
src-tauri/Cargo.lock
generated
@@ -7581,7 +7581,6 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_yaml",
|
||||
"sqlx",
|
||||
"tauri",
|
||||
"tauri-build",
|
||||
"tauri-plugin-clipboard-manager",
|
||||
@@ -7615,6 +7614,7 @@ dependencies = [
|
||||
"sea-query-rusqlite",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sqlx",
|
||||
"tauri",
|
||||
"thiserror",
|
||||
"ts-rs",
|
||||
|
||||
@@ -43,7 +43,6 @@ reqwest_cookie_store = "0.8.0"
|
||||
serde = { version = "1.0.198", features = ["derive"] }
|
||||
serde_json = { version = "1.0.116", features = ["raw_value"] }
|
||||
serde_yaml = "0.9.34"
|
||||
sqlx = { version = "0.8.0", features = ["sqlite", "runtime-tokio-rustls"] }
|
||||
tauri = { workspace = true }
|
||||
tauri-plugin-shell = { workspace = true }
|
||||
tauri-plugin-clipboard-manager = "2.0.0-rc.0"
|
||||
|
||||
@@ -2,8 +2,7 @@ use std::fmt::Display;
|
||||
|
||||
use log::{debug, info};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::json;
|
||||
use sqlx::types::JsonValue;
|
||||
use serde_json::{json, Value};
|
||||
use tauri::{AppHandle, Manager};
|
||||
|
||||
use yaak_models::queries::{generate_id, get_key_value_int, get_key_value_string, set_key_value_int, set_key_value_string};
|
||||
@@ -155,7 +154,7 @@ pub async fn track_event(
|
||||
app_handle: &AppHandle,
|
||||
resource: AnalyticsResource,
|
||||
action: AnalyticsAction,
|
||||
attributes: Option<JsonValue>,
|
||||
attributes: Option<Value>,
|
||||
) {
|
||||
let id = get_id(app_handle).await;
|
||||
let event = format!("{}.{}", resource, action);
|
||||
|
||||
@@ -17,10 +17,6 @@ use fern::colors::ColoredLevelConfig;
|
||||
use log::{debug, error, info, warn};
|
||||
use rand::random;
|
||||
use serde_json::{json, Value};
|
||||
use sqlx::migrate::Migrator;
|
||||
use sqlx::sqlite::SqliteConnectOptions;
|
||||
use sqlx::{Pool, Sqlite, SqlitePool};
|
||||
use tauri::path::BaseDirectory;
|
||||
use tauri::Listener;
|
||||
#[cfg(target_os = "macos")]
|
||||
use tauri::TitleBarStyle;
|
||||
@@ -76,19 +72,6 @@ mod window_menu;
|
||||
const DEFAULT_WINDOW_WIDTH: f64 = 1100.0;
|
||||
const DEFAULT_WINDOW_HEIGHT: f64 = 600.0;
|
||||
|
||||
async fn migrate_db(app_handle: &AppHandle, pool: &Pool<Sqlite>) -> Result<(), String> {
|
||||
let p = app_handle
|
||||
.path()
|
||||
.resolve("migrations", BaseDirectory::Resource)
|
||||
.expect("failed to resolve resource");
|
||||
info!("Running migrations at {}", p.to_string_lossy());
|
||||
let mut m = Migrator::new(p).await.expect("Failed to load migrations");
|
||||
m.set_ignore_missing(true); // So we can rollback versions and not crash
|
||||
m.run(pool).await.expect("Failed to run migrations");
|
||||
info!("Migrations complete!");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize)]
|
||||
#[serde(default, rename_all = "camelCase")]
|
||||
struct AppMetaData {
|
||||
@@ -1639,28 +1622,7 @@ pub fn run() {
|
||||
builder
|
||||
.setup(|app| {
|
||||
let app_data_dir = app.path().app_data_dir().unwrap();
|
||||
let app_config_dir = app.path().app_config_dir().unwrap();
|
||||
info!(
|
||||
"App Config Dir: {}",
|
||||
app_config_dir.as_path().to_string_lossy(),
|
||||
);
|
||||
info!("App Data Dir: {}", app_data_dir.as_path().to_string_lossy());
|
||||
let app_data_dir = match is_dev() {
|
||||
true => current_dir().unwrap(),
|
||||
false => app_data_dir,
|
||||
};
|
||||
|
||||
create_dir_all(app_data_dir.clone()).expect("Problem creating App directory!");
|
||||
let p = app_data_dir.join("db.sqlite");
|
||||
File::options()
|
||||
.write(true)
|
||||
.create(true)
|
||||
.open(&p)
|
||||
.expect("Problem creating database file!");
|
||||
|
||||
let p_string = p.to_string_lossy().replace(' ', "%20");
|
||||
let url = format!("sqlite://{}?mode=rwc", p_string);
|
||||
info!("Connecting to database at {}", url);
|
||||
|
||||
// Add updater
|
||||
let yaak_updater = YaakUpdater::new();
|
||||
@@ -1678,20 +1640,6 @@ pub fn run() {
|
||||
let grpc_handle = GrpcHandle::new(&app.app_handle());
|
||||
app.manage(Mutex::new(grpc_handle));
|
||||
|
||||
// Add DB handle
|
||||
tauri::async_runtime::block_on(async move {
|
||||
let opts = SqliteConnectOptions::from_str(p.to_str().unwrap()).unwrap();
|
||||
let pool = SqlitePool::connect_with(opts)
|
||||
.await
|
||||
.expect("Failed to connect to database");
|
||||
migrate_db(app.handle(), &pool)
|
||||
.await
|
||||
.expect("Failed to migrate database");
|
||||
let h = app.handle();
|
||||
let _ = cancel_pending_responses(h).await;
|
||||
let _ = cancel_pending_grpc_connections(h).await;
|
||||
});
|
||||
|
||||
Ok(())
|
||||
})
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
@@ -1774,6 +1722,13 @@ pub fn run() {
|
||||
let info = analytics::track_launch_event(&h).await;
|
||||
debug!("Launched Yaak {:?}", info);
|
||||
});
|
||||
|
||||
// Cancel pending requests
|
||||
let h = app_handle.clone();
|
||||
tauri::async_runtime::block_on(async move {
|
||||
let _ = cancel_pending_responses(&h).await;
|
||||
let _ = cancel_pending_grpc_connections(&h).await;
|
||||
});
|
||||
}
|
||||
RunEvent::WindowEvent {
|
||||
event: WindowEvent::Focused(true),
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
use std::time::SystemTime;
|
||||
|
||||
use crate::analytics::get_num_launches;
|
||||
use chrono::{DateTime, Duration, Utc};
|
||||
use log::debug;
|
||||
use reqwest::Method;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tauri::{AppHandle, Emitter};
|
||||
use yaak_models::queries::{get_key_value_raw, set_key_value_raw};
|
||||
use crate::analytics::get_num_launches;
|
||||
|
||||
// Check for updates every hour
|
||||
const MAX_UPDATE_CHECK_SECONDS: u64 = 60 * 60;
|
||||
@@ -19,7 +19,7 @@ pub struct YaakNotifier {
|
||||
last_check: SystemTime,
|
||||
}
|
||||
|
||||
#[derive(sqlx::FromRow, Debug, Clone, Serialize, Deserialize, Default)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
||||
#[serde(default, rename_all = "camelCase")]
|
||||
pub struct YaakNotification {
|
||||
timestamp: DateTime<Utc>,
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use sqlx::types::JsonValue;
|
||||
|
||||
use serde_json::Value;
|
||||
use crate::template_fns::timestamp;
|
||||
use templates::parse_and_render;
|
||||
use yaak_models::models::{
|
||||
@@ -41,9 +39,9 @@ pub fn render_request(r: &HttpRequest, w: &Workspace, e: Option<&Environment>) -
|
||||
} else {
|
||||
v.to_string()
|
||||
};
|
||||
(render(k, vars), JsonValue::from(v))
|
||||
(render(k, vars), Value::from(v))
|
||||
})
|
||||
.collect::<HashMap<String, JsonValue>>(),
|
||||
.collect::<HashMap<String, Value>>(),
|
||||
authentication: r
|
||||
.authentication
|
||||
.iter()
|
||||
@@ -53,9 +51,9 @@ pub fn render_request(r: &HttpRequest, w: &Workspace, e: Option<&Environment>) -
|
||||
} else {
|
||||
v.to_string()
|
||||
};
|
||||
(render(k, vars), JsonValue::from(v))
|
||||
(render(k, vars), Value::from(v))
|
||||
})
|
||||
.collect::<HashMap<String, JsonValue>>(),
|
||||
.collect::<HashMap<String, Value>>(),
|
||||
..r
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ serde_json = "1.0.122"
|
||||
thiserror = "1.0.63"
|
||||
ts-rs = { version = "9.0.1", features = ["chrono-impl", "serde-json-impl"] }
|
||||
tauri = { workspace = true }
|
||||
sqlx = { version = "0.8.0", features = ["sqlite", "runtime-tokio-rustls"] }
|
||||
log = "0.4.22"
|
||||
rand = "0.8.5"
|
||||
r2d2 = "0.8.10"
|
||||
|
||||
@@ -2,12 +2,17 @@ use log::info;
|
||||
use r2d2::Pool;
|
||||
use r2d2_sqlite::SqliteConnectionManager;
|
||||
use serde::Deserialize;
|
||||
use std::env::current_dir;
|
||||
use std::fs::create_dir_all;
|
||||
use sqlx::migrate::Migrator;
|
||||
use sqlx::sqlite::SqliteConnectOptions;
|
||||
use sqlx::SqlitePool;
|
||||
use std::fs::{create_dir_all, File};
|
||||
use std::path::PathBuf;
|
||||
use std::str::FromStr;
|
||||
use std::time::Duration;
|
||||
use tauri::async_runtime::Mutex;
|
||||
use tauri::path::BaseDirectory;
|
||||
use tauri::plugin::TauriPlugin;
|
||||
use tauri::{is_dev, plugin, Manager, Runtime};
|
||||
use tauri::{plugin, AppHandle, Manager, Runtime};
|
||||
|
||||
pub struct SqliteConnection(pub Mutex<Pool<SqliteConnectionManager>>);
|
||||
|
||||
@@ -30,20 +35,23 @@ impl Builder {
|
||||
pub fn build<R: Runtime>(&self) -> TauriPlugin<R, Option<PluginConfig>> {
|
||||
plugin::Builder::<R, Option<PluginConfig>>::new("yaak_models")
|
||||
.setup(|app, _api| {
|
||||
let app_path = match is_dev() {
|
||||
true => current_dir().unwrap(),
|
||||
false => app.path().app_data_dir().unwrap(),
|
||||
};
|
||||
|
||||
let app_path = app.path().app_data_dir().unwrap();
|
||||
create_dir_all(app_path.clone()).expect("Problem creating App directory!");
|
||||
|
||||
let db_file_path = app_path.join("db.sqlite");
|
||||
info!("Opening SQLite DB at {db_file_path:?}");
|
||||
|
||||
{
|
||||
let db_file_path = db_file_path.clone();
|
||||
tauri::async_runtime::block_on(async move {
|
||||
must_migrate_db(app.app_handle(), &db_file_path).await;
|
||||
});
|
||||
};
|
||||
|
||||
let manager = SqliteConnectionManager::file(db_file_path);
|
||||
let pool = Pool::builder()
|
||||
.max_size(1000) // Up from 10 (just in case)
|
||||
.connection_timeout(Duration::from_secs(10))
|
||||
.max_size(100) // Up from 10 (just in case)
|
||||
.connection_timeout(Duration::from_secs(10)) // Down from 30
|
||||
.build(manager)
|
||||
.unwrap();
|
||||
|
||||
@@ -54,3 +62,35 @@ impl Builder {
|
||||
.build()
|
||||
}
|
||||
}
|
||||
|
||||
async fn must_migrate_db<R: Runtime>(app_handle: &AppHandle<R>, path: &PathBuf) {
|
||||
let app_data_dir = app_handle.path().app_data_dir().unwrap();
|
||||
let sqlite_file_path = app_data_dir.join("db.sqlite");
|
||||
|
||||
info!("Creating database file at {:?}", sqlite_file_path);
|
||||
File::options()
|
||||
.write(true)
|
||||
.create(true)
|
||||
.open(&sqlite_file_path)
|
||||
.expect("Problem creating database file!");
|
||||
|
||||
let p_string = sqlite_file_path.to_string_lossy().replace(' ', "%20");
|
||||
let url = format!("sqlite://{}?mode=rwc", p_string);
|
||||
|
||||
info!("Connecting to database at {}", url);
|
||||
let opts = SqliteConnectOptions::from_str(path.to_string_lossy().to_string().as_str()).unwrap();
|
||||
let pool = SqlitePool::connect_with(opts)
|
||||
.await
|
||||
.expect("Failed to connect to database");
|
||||
let p = app_handle
|
||||
.path()
|
||||
.resolve("migrations", BaseDirectory::Resource)
|
||||
.expect("failed to resolve resource");
|
||||
|
||||
info!("Running database migrations from: {}", p.to_string_lossy());
|
||||
let mut m = Migrator::new(p).await.expect("Failed to load migrations");
|
||||
m.set_ignore_missing(true); // So we can roll back versions and not crash
|
||||
m.run(&pool).await.expect("Failed to run migrations");
|
||||
|
||||
info!("Database migrations complete");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user