mirror of
https://github.com/haileys/mixlab.git
synced 2026-06-16 12:59:40 +02:00
hook up beginnings of sqlite persistence
This commit is contained in:
@@ -10,7 +10,7 @@ release:
|
||||
./frontend-exec.sh ./build.sh --release && cargo build --release
|
||||
|
||||
run:
|
||||
./frontend-exec.sh ./build.sh && cargo run workspace/
|
||||
./frontend-exec.sh ./build.sh && cargo run workspace
|
||||
|
||||
check:
|
||||
./frontend-exec.sh cargo check --target=wasm32-unknown-unknown && cargo check
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
pub static MIGRATIONS: &'static [(i32, &'static str)] = &[
|
||||
(0, include_str!("migrations/0_init.sql")),
|
||||
// (20200804, include_str!("migrations/20200804_create_media_tables.sql")),
|
||||
];
|
||||
@@ -0,0 +1 @@
|
||||
CREATE TABLE schema_migrations (version INTEGER NOT NULL);
|
||||
@@ -0,0 +1,57 @@
|
||||
use std::path::Path;
|
||||
|
||||
use sqlx::sqlite::{SqlitePool, SqliteConnectOptions};
|
||||
|
||||
mod migrations;
|
||||
|
||||
async fn schema_version(pool: &SqlitePool) -> Result<Option<i32>, sqlx::Error> {
|
||||
let result = sqlx::query_as::<_, (i32,)>("SELECT version FROM schema_migrations WHERE rowid = 1")
|
||||
.fetch_one(pool)
|
||||
.await;
|
||||
|
||||
match result {
|
||||
Ok((schema_version,)) => Ok(Some(schema_version)),
|
||||
Err(sqlx::Error::Database(e)) if e.message() == "no such table: schema_migrations" => Ok(None),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
|
||||
async fn update_schema_version(pool: &SqlitePool, ver: i32) -> Result<(), sqlx::Error> {
|
||||
sqlx::query(r"
|
||||
INSERT INTO schema_migrations (rowid, version) VALUES (1, ?)
|
||||
ON CONFLICT (rowid) DO UPDATE SET version = excluded.version;
|
||||
")
|
||||
.bind(ver)
|
||||
.execute(pool)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn attach(path: &Path) -> Result<SqlitePool, sqlx::Error> {
|
||||
let pool = SqlitePool::connect_with(SqliteConnectOptions::new()
|
||||
.filename(path)
|
||||
.create_if_missing(true)).await?;
|
||||
|
||||
let schema_version = schema_version(&pool).await?;
|
||||
|
||||
let mut migrations = migrations::MIGRATIONS.to_vec();
|
||||
|
||||
// migrations should already be sorted, but we should ensure it is anyway:
|
||||
migrations.sort_by_key(|(ver, _)| *ver);
|
||||
|
||||
// retain only migrations yet to be performed on this database
|
||||
migrations.retain(|(ver, _)| Some(*ver) > schema_version);
|
||||
|
||||
// run migrations to bring database up to date
|
||||
for (_, sql) in &migrations {
|
||||
sqlx::query(sql).execute(&pool).await?;
|
||||
}
|
||||
|
||||
// update database schema version if migrations were performed
|
||||
if let Some((ver, _)) = migrations.last() {
|
||||
update_schema_version(&pool, *ver).await?;
|
||||
}
|
||||
|
||||
Ok(pool)
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
mod db;
|
||||
mod engine;
|
||||
mod icecast;
|
||||
mod listen;
|
||||
|
||||
+18
-10
@@ -4,6 +4,7 @@ use std::sync::Arc;
|
||||
|
||||
use derive_more::From;
|
||||
use futures::stream::Stream;
|
||||
use sqlx::SqlitePool;
|
||||
use tokio::fs::{self, File};
|
||||
use tokio::io::{self, AsyncWriteExt};
|
||||
use tokio::sync::Mutex;
|
||||
@@ -12,6 +13,7 @@ use uuid::Uuid;
|
||||
|
||||
use mixlab_protocol::{WorkspaceState, PerformanceInfo};
|
||||
|
||||
use crate::db;
|
||||
use crate::engine::{self, EngineHandle, EngineEvents, EngineError, EngineSession, WorkspaceEmbryo};
|
||||
use crate::persist;
|
||||
|
||||
@@ -23,7 +25,7 @@ pub struct ProjectHandle {
|
||||
|
||||
struct ProjectBase {
|
||||
path: PathBuf,
|
||||
library: HashMap<Uuid, MediaInfo>,
|
||||
database: SqlitePool,
|
||||
}
|
||||
|
||||
type ProjectBaseRef = Arc<Mutex<ProjectBase>>;
|
||||
@@ -32,15 +34,21 @@ type ProjectBaseRef = Arc<Mutex<ProjectBase>>;
|
||||
pub enum OpenError {
|
||||
Io(io::Error),
|
||||
Json(serde_json::Error),
|
||||
Database(sqlx::Error),
|
||||
NotDirectory,
|
||||
}
|
||||
|
||||
impl ProjectBase {
|
||||
fn open_at(path: PathBuf) -> Self {
|
||||
ProjectBase {
|
||||
async fn attach(path: PathBuf) -> Result<Self, sqlx::Error> {
|
||||
let mut sqlite_path = path.clone();
|
||||
sqlite_path.set_extension("mixlab");
|
||||
|
||||
let database = db::attach(&sqlite_path).await?;
|
||||
|
||||
Ok(ProjectBase {
|
||||
path,
|
||||
library: HashMap::new(),
|
||||
}
|
||||
database,
|
||||
})
|
||||
}
|
||||
|
||||
async fn read_workspace(&self) -> Result<persist::Workspace, io::Error> {
|
||||
@@ -91,10 +99,10 @@ impl ProjectBase {
|
||||
}
|
||||
|
||||
async fn finalize_media_upload(&mut self, id: Uuid, info: UploadInfo) -> Result<(), io::Error> {
|
||||
self.library.insert(id, MediaInfo {
|
||||
name: info.name,
|
||||
kind: info.kind,
|
||||
});
|
||||
// self.library.insert(id, MediaInfo {
|
||||
// name: info.name,
|
||||
// kind: info.kind,
|
||||
// });
|
||||
|
||||
// TODO persist
|
||||
|
||||
@@ -124,7 +132,7 @@ pub async fn open_or_create(path: PathBuf) -> Result<ProjectHandle, OpenError> {
|
||||
}
|
||||
}
|
||||
|
||||
let base = ProjectBase::open_at(path);
|
||||
let base = ProjectBase::attach(path).await?;
|
||||
let workspace = base.read_workspace().await?;
|
||||
|
||||
// start engine update thread
|
||||
|
||||
Reference in New Issue
Block a user