Fix up DB creation and migration

This commit is contained in:
Gregory Schier
2024-08-09 11:20:04 -07:00
parent 411fd4f530
commit 1a9dfda90c
10 changed files with 113 additions and 121 deletions

88
package-lock.json generated
View File

@@ -57,7 +57,7 @@
"devDependencies": {
"@tailwindcss/nesting": "^0.0.0-insiders.565cd3e",
"@tanstack/react-query-devtools": "^5.45.1",
"@tauri-apps/cli": "^2.0.0-rc.1",
"@tauri-apps/cli": "^2.0.0-rc.2",
"@types/node": "^18.7.10",
"@types/papaparse": "^5.3.7",
"@types/parse-color": "^1.0.1",
@@ -2357,9 +2357,9 @@
}
},
"node_modules/@tauri-apps/cli": {
"version": "2.0.0-rc.1",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-2.0.0-rc.1.tgz",
"integrity": "sha512-9AzVrUMdb6EZ/Lwtdqt03XqqG6d/3gTJPOw2E9zmCHprJWEwqEp4JIVHYYfrqkkZyKclD3m5ggXwfYwclcYLdw==",
"version": "2.0.0-rc.3",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-2.0.0-rc.3.tgz",
"integrity": "sha512-iNF95pieBmverl1EmQyqh+fhcIClS544fN5Ex5lAbYLTiHZ/gm3lOfVBhF6NPaKd/sfLuy7K1tfDXlHztBfANw==",
"dev": true,
"bin": {
"tauri": "tauri.js"
@@ -2372,22 +2372,22 @@
"url": "https://opencollective.com/tauri"
},
"optionalDependencies": {
"@tauri-apps/cli-darwin-arm64": "2.0.0-rc.1",
"@tauri-apps/cli-darwin-x64": "2.0.0-rc.1",
"@tauri-apps/cli-linux-arm-gnueabihf": "2.0.0-rc.1",
"@tauri-apps/cli-linux-arm64-gnu": "2.0.0-rc.1",
"@tauri-apps/cli-linux-arm64-musl": "2.0.0-rc.1",
"@tauri-apps/cli-linux-x64-gnu": "2.0.0-rc.1",
"@tauri-apps/cli-linux-x64-musl": "2.0.0-rc.1",
"@tauri-apps/cli-win32-arm64-msvc": "2.0.0-rc.1",
"@tauri-apps/cli-win32-ia32-msvc": "2.0.0-rc.1",
"@tauri-apps/cli-win32-x64-msvc": "2.0.0-rc.1"
"@tauri-apps/cli-darwin-arm64": "2.0.0-rc.3",
"@tauri-apps/cli-darwin-x64": "2.0.0-rc.3",
"@tauri-apps/cli-linux-arm-gnueabihf": "2.0.0-rc.3",
"@tauri-apps/cli-linux-arm64-gnu": "2.0.0-rc.3",
"@tauri-apps/cli-linux-arm64-musl": "2.0.0-rc.3",
"@tauri-apps/cli-linux-x64-gnu": "2.0.0-rc.3",
"@tauri-apps/cli-linux-x64-musl": "2.0.0-rc.3",
"@tauri-apps/cli-win32-arm64-msvc": "2.0.0-rc.3",
"@tauri-apps/cli-win32-ia32-msvc": "2.0.0-rc.3",
"@tauri-apps/cli-win32-x64-msvc": "2.0.0-rc.3"
}
},
"node_modules/@tauri-apps/cli-darwin-arm64": {
"version": "2.0.0-rc.1",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-2.0.0-rc.1.tgz",
"integrity": "sha512-dJxyAi4P9fOkklBZXuwUVnHgdM/20fgM4zYdfejQfju5+q9GUqnMbrrIUqlJbQGf8EnrIdSWnieO8wU8GOwT0g==",
"version": "2.0.0-rc.3",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-2.0.0-rc.3.tgz",
"integrity": "sha512-szYCSr/ChbCF+S6Wnr15TYpI2cZR07d+AQOiFGuScP0preM8Pbsk/sb0hfLwqzepjVFFNVWQba9sG7FEW2Y2XA==",
"cpu": [
"arm64"
],
@@ -2401,9 +2401,9 @@
}
},
"node_modules/@tauri-apps/cli-darwin-x64": {
"version": "2.0.0-rc.1",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-2.0.0-rc.1.tgz",
"integrity": "sha512-dwrqLzNIFk8a1Vf2YI8axHm7uvLfo4M4TSWCw2ZkgeSGWWK6Y6CYVZbBEjOEGIOf+GFAa9rVOSZRuMwpiufNng==",
"version": "2.0.0-rc.3",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-2.0.0-rc.3.tgz",
"integrity": "sha512-BJv6EJOY1DJbRzVtfg8CcBAlnS5OjhBAc5YKjh4BT7EyOcop8HStBSxhL6yjWrUP7eLR1iIsW/uSehVJwzYIdQ==",
"cpu": [
"x64"
],
@@ -2417,9 +2417,9 @@
}
},
"node_modules/@tauri-apps/cli-linux-arm-gnueabihf": {
"version": "2.0.0-rc.1",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-2.0.0-rc.1.tgz",
"integrity": "sha512-jvMF4UNc3Jr/xHnw+4NNsWfk8WrcFrQVImAtKlCev9QepqfBmDh+FgXTvfysoBCSxEBS626TvYms3OhI0LOO4A==",
"version": "2.0.0-rc.3",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-2.0.0-rc.3.tgz",
"integrity": "sha512-fwx805/xL4sF/EdMYqcUHQHzMYwo+OVTBTz5x/JWK8D57rnmLHAP+ZhnfFsZQLRo2QRT2l1Ye3bDyU+QRA1JFA==",
"cpu": [
"arm"
],
@@ -2433,9 +2433,9 @@
}
},
"node_modules/@tauri-apps/cli-linux-arm64-gnu": {
"version": "2.0.0-rc.1",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-2.0.0-rc.1.tgz",
"integrity": "sha512-TGmadGW8BjTq864AYrv/u+vTnAodnOuzv1VCUOV23O8st35GZG6V47jwNsSjQjhrcO1XzmJiRAtrcVKuTZ/xUA==",
"version": "2.0.0-rc.3",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-2.0.0-rc.3.tgz",
"integrity": "sha512-3KauzO1Ls4kuY0nr82S4X8XFxlQAMN+Mqp8LLqvQ+PPMp92XQAkPH7osQdoHIEoW5gsE69U2JaiQ5tHSqNM9og==",
"cpu": [
"arm64"
],
@@ -2449,9 +2449,9 @@
}
},
"node_modules/@tauri-apps/cli-linux-arm64-musl": {
"version": "2.0.0-rc.1",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.0.0-rc.1.tgz",
"integrity": "sha512-+SJsRTW0PvvD7awEn+tIPJ3s12s6RpKXdOib2mztoKocasrGRfz+EFZuXc42Iwk3xROsrQkiw2UAmcNLkW5NwA==",
"version": "2.0.0-rc.3",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.0.0-rc.3.tgz",
"integrity": "sha512-ngHS0foffm1xO5gqnDKGeYMKj8ceGmrFP5dDldoaaMQubw1SyFa0pRUjb7fZSYiO7F4SOSa8NYeMqlF9peZmnQ==",
"cpu": [
"arm64"
],
@@ -2465,9 +2465,9 @@
}
},
"node_modules/@tauri-apps/cli-linux-x64-gnu": {
"version": "2.0.0-rc.1",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-2.0.0-rc.1.tgz",
"integrity": "sha512-vjPrj2btS97IOp6cU42IrkI49SQZDSg8TPqwOwFqyQeAotCT1i0F38pLZWe1gLyPUowO8XdaaBdwYg6IRDKcZg==",
"version": "2.0.0-rc.3",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-2.0.0-rc.3.tgz",
"integrity": "sha512-0/am9pVvuUHGmz32M8ffz1fpLnc08j3nzcRe5wUdL2AxfT+wKMII+Dn99GtCVgcdDW4jSXDMRUwrBkGocGC2OA==",
"cpu": [
"x64"
],
@@ -2481,9 +2481,9 @@
}
},
"node_modules/@tauri-apps/cli-linux-x64-musl": {
"version": "2.0.0-rc.1",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-2.0.0-rc.1.tgz",
"integrity": "sha512-MrE68/u6rMrkM1uM/DR1MNnMXiYebhSPGqqxshJ12SmFdk3yQ/Z73Wzvk8xv78eOExh4lTtEXI22YwaBCf9AEg==",
"version": "2.0.0-rc.3",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-2.0.0-rc.3.tgz",
"integrity": "sha512-r7mRi8q8TqTFVjb9kAsU7IgwUgno2s8Ip4xwq9psQhlRE3JGEZQmSEcy1jqTjfl6KFh6lJcDR7l+9/EMhL/D3Q==",
"cpu": [
"x64"
],
@@ -2497,9 +2497,9 @@
}
},
"node_modules/@tauri-apps/cli-win32-arm64-msvc": {
"version": "2.0.0-rc.1",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-2.0.0-rc.1.tgz",
"integrity": "sha512-SLulbiUjg8BGf/zX+U1PGjB+JpsN2nLRGuW07BYwSDW3s3mp2aagLuOwaTaOPBrDzfIMRYq8KT54A4jfRjEZlg==",
"version": "2.0.0-rc.3",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-2.0.0-rc.3.tgz",
"integrity": "sha512-2J6KjmDIQCw6HF1X6/yPcd+JLl7pxrH2zVMGmNllaoWhHeByvRobqFWnT7gcdHaA3dGTo432CwWvOgTgrINQpQ==",
"cpu": [
"arm64"
],
@@ -2513,9 +2513,9 @@
}
},
"node_modules/@tauri-apps/cli-win32-ia32-msvc": {
"version": "2.0.0-rc.1",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-2.0.0-rc.1.tgz",
"integrity": "sha512-rz85riTjcWdZlgTku6HcBx625Otdc0/NwDjRXgdXakL1ybw7E+G5YlLZNcQX25u17RKUAWX/2/VZ1pSz945Ovw==",
"version": "2.0.0-rc.3",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-2.0.0-rc.3.tgz",
"integrity": "sha512-8q75CsHDSEDdgi6xPwim+BaQZFCswK2Dn/qL38V3Mh9kmVvC8oGJMPC66bC20dF+v3KWeFm2FNNGQqOSXCveHg==",
"cpu": [
"ia32"
],
@@ -2529,9 +2529,9 @@
}
},
"node_modules/@tauri-apps/cli-win32-x64-msvc": {
"version": "2.0.0-rc.1",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-2.0.0-rc.1.tgz",
"integrity": "sha512-aRO70dDbn4w3CbALMG+b7g460xmbSTuUiGmRh0r/MNVeoZk/YbqluBUyhXdWGxJb8OVubw/4RlczKYcPmJceMw==",
"version": "2.0.0-rc.3",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-2.0.0-rc.3.tgz",
"integrity": "sha512-qeBRJYalahxEXolekcpZJ/HBrIJacG2NWJBGhhi797mIwnbmlpbHMc8blIJtNNNwVUb2BjXuxKQVfojQ5YYrcg==",
"cpu": [
"x64"
],

View File

@@ -72,7 +72,7 @@
"devDependencies": {
"@tailwindcss/nesting": "^0.0.0-insiders.565cd3e",
"@tanstack/react-query-devtools": "^5.45.1",
"@tauri-apps/cli": "^2.0.0-rc.1",
"@tauri-apps/cli": "^2.0.0-rc.2",
"@types/node": "^18.7.10",
"@types/papaparse": "^5.3.7",
"@types/parse-color": "^1.0.1",

2
src-tauri/Cargo.lock generated
View File

@@ -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",

View File

@@ -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"

View File

@@ -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);

View File

@@ -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),

View File

@@ -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>,

View File

@@ -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
}
}

View File

@@ -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"

View File

@@ -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");
}