Convert to SQLx and SQLite #64
|
@ -38,6 +38,7 @@ phf = { version = "0.8", features = ["macros"] }
|
||||||
matrix-sdk = { git = "https://github.com/matrix-org/matrix-rust-sdk", branch = "master" }
|
matrix-sdk = { git = "https://github.com/matrix-org/matrix-rust-sdk", branch = "master" }
|
||||||
refinery = { version = "0.5", features = ["rusqlite"]}
|
refinery = { version = "0.5", features = ["rusqlite"]}
|
||||||
barrel = { version = "0.6", features = ["sqlite3"] }
|
barrel = { version = "0.6", features = ["sqlite3"] }
|
||||||
|
tempfile = "3"
|
||||||
|
|
||||||
[dependencies.sqlx]
|
[dependencies.sqlx]
|
||||||
version = "0.5"
|
version = "0.5"
|
||||||
|
@ -50,6 +51,3 @@ features = ['derive']
|
||||||
[dependencies.tokio]
|
[dependencies.tokio]
|
||||||
version = "1"
|
version = "1"
|
||||||
features = [ "full" ]
|
features = [ "full" ]
|
||||||
|
|
||||||
[dev-dependencies]
|
|
||||||
tempfile = "3"
|
|
|
@ -15,9 +15,17 @@ async fn main() -> Result<(), BotError> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let homeserver = Url::parse("http://example.com")?;
|
let homeserver = Url::parse("http://example.com")?;
|
||||||
|
let db_path = tempfile::NamedTempFile::new_in(".").unwrap();
|
||||||
|
let db = Database::new(
|
||||||
|
db_path
|
||||||
|
.path()
|
||||||
|
.to_str()
|
||||||
|
.expect("Could not get path to temporary db"),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
let context = Context {
|
let context = Context {
|
||||||
db: Database::new_temp().await?,
|
db: db,
|
||||||
matrix_client: &matrix_sdk::Client::new(homeserver)
|
matrix_client: &matrix_sdk::Client::new(homeserver)
|
||||||
.expect("Could not create matrix client"),
|
.expect("Could not create matrix client"),
|
||||||
room: RoomContext {
|
room: RoomContext {
|
||||||
|
|
|
@ -7,7 +7,6 @@ use tenebrous_dicebot::bot::DiceBot;
|
||||||
use tenebrous_dicebot::config::*;
|
use tenebrous_dicebot::config::*;
|
||||||
use tenebrous_dicebot::db::sqlite::Database;
|
use tenebrous_dicebot::db::sqlite::Database;
|
||||||
use tenebrous_dicebot::error::BotError;
|
use tenebrous_dicebot::error::BotError;
|
||||||
use tenebrous_dicebot::migrator;
|
|
||||||
use tenebrous_dicebot::state::DiceBotState;
|
use tenebrous_dicebot::state::DiceBotState;
|
||||||
use tracing_subscriber::filter::EnvFilter;
|
use tracing_subscriber::filter::EnvFilter;
|
||||||
|
|
||||||
|
@ -38,8 +37,6 @@ async fn run() -> Result<(), BotError> {
|
||||||
let db = Database::new(&sqlite_path).await?;
|
let db = Database::new(&sqlite_path).await?;
|
||||||
let state = Arc::new(RwLock::new(DiceBotState::new(&cfg)));
|
let state = Arc::new(RwLock::new(DiceBotState::new(&cfg)));
|
||||||
|
|
||||||
migrator::migrate(&sqlite_path).await?;
|
|
||||||
|
|
||||||
match DiceBot::new(&cfg, &state, &db) {
|
match DiceBot::new(&cfg, &state, &db) {
|
||||||
Ok(bot) => bot.run().await?,
|
Ok(bot) => bot.run().await?,
|
||||||
Err(e) => println!("Error connecting: {:?}", e),
|
Err(e) => println!("Error connecting: {:?}", e),
|
||||||
|
|
|
@ -475,8 +475,12 @@ mod tests {
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
||||||
async fn rejects_large_expression_test() {
|
async fn rejects_large_expression_test() {
|
||||||
|
let db_path = tempfile::NamedTempFile::new_in(".").unwrap();
|
||||||
let homeserver = Url::parse("http://example.com").unwrap();
|
let homeserver = Url::parse("http://example.com").unwrap();
|
||||||
let db = Database::new_temp().await.unwrap();
|
let db = Database::new(db_path.path().to_str().unwrap())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let ctx = Context {
|
let ctx = Context {
|
||||||
db: db,
|
db: db,
|
||||||
matrix_client: &matrix_sdk::Client::new(homeserver).unwrap(),
|
matrix_client: &matrix_sdk::Client::new(homeserver).unwrap(),
|
||||||
|
@ -508,7 +512,7 @@ mod tests {
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
||||||
async fn converts_to_chance_die_test() {
|
async fn converts_to_chance_die_test() {
|
||||||
let db_path = tempfile::NamedTempFile::new_in(".").unwrap();
|
let db_path = tempfile::NamedTempFile::new_in(".").unwrap();
|
||||||
crate::migrator::migrate(db_path.path().to_str().unwrap())
|
crate::db::sqlite::migrator::migrate(db_path.path().to_str().unwrap())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -545,7 +549,7 @@ mod tests {
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
||||||
async fn can_resolve_variables_test() {
|
async fn can_resolve_variables_test() {
|
||||||
let db_path = tempfile::NamedTempFile::new_in(".").unwrap();
|
let db_path = tempfile::NamedTempFile::new_in(".").unwrap();
|
||||||
crate::migrator::migrate(db_path.path().to_str().unwrap())
|
crate::db::sqlite::migrator::migrate(db_path.path().to_str().unwrap())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|
|
@ -138,8 +138,13 @@ mod tests {
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
||||||
async fn unrecognized_command() {
|
async fn unrecognized_command() {
|
||||||
let db = crate::db::sqlite::Database::new_temp().await.unwrap();
|
let db_path = tempfile::NamedTempFile::new_in(".").unwrap();
|
||||||
|
let db = crate::db::sqlite::Database::new(db_path.path().to_str().unwrap())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let homeserver = Url::parse("http://example.com").unwrap();
|
let homeserver = Url::parse("http://example.com").unwrap();
|
||||||
|
|
||||||
let ctx = Context {
|
let ctx = Context {
|
||||||
db: db,
|
db: db,
|
||||||
matrix_client: &matrix_sdk::Client::new(homeserver).unwrap(),
|
matrix_client: &matrix_sdk::Client::new(homeserver).unwrap(),
|
||||||
|
|
|
@ -493,7 +493,7 @@ mod tests {
|
||||||
};
|
};
|
||||||
|
|
||||||
let db_path = tempfile::NamedTempFile::new_in(".").unwrap();
|
let db_path = tempfile::NamedTempFile::new_in(".").unwrap();
|
||||||
crate::migrator::migrate(db_path.path().to_str().unwrap())
|
crate::db::sqlite::migrator::migrate(db_path.path().to_str().unwrap())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -529,7 +529,7 @@ mod tests {
|
||||||
};
|
};
|
||||||
|
|
||||||
let db_path = tempfile::NamedTempFile::new_in(".").unwrap();
|
let db_path = tempfile::NamedTempFile::new_in(".").unwrap();
|
||||||
crate::migrator::migrate(db_path.path().to_str().unwrap())
|
crate::db::sqlite::migrator::migrate(db_path.path().to_str().unwrap())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -565,7 +565,7 @@ mod tests {
|
||||||
};
|
};
|
||||||
|
|
||||||
let db_path = tempfile::NamedTempFile::new_in(".").unwrap();
|
let db_path = tempfile::NamedTempFile::new_in(".").unwrap();
|
||||||
crate::migrator::migrate(db_path.path().to_str().unwrap())
|
crate::db::sqlite::migrator::migrate(db_path.path().to_str().unwrap())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|
|
@ -3,20 +3,6 @@ use std::num::TryFromIntError;
|
||||||
use sled::transaction::{TransactionError, UnabortableTransactionError};
|
use sled::transaction::{TransactionError, UnabortableTransactionError};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
|
||||||
pub enum MigrationError {
|
|
||||||
#[error("cannot downgrade to an older database version")]
|
|
||||||
CannotDowngrade,
|
|
||||||
|
|
||||||
#[error("migration for version {0} not defined")]
|
|
||||||
MigrationNotFound(u32),
|
|
||||||
|
|
||||||
#[error("migration failed: {0}")]
|
|
||||||
MigrationFailed(String),
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO better combining of key and value in certain errors (namely
|
|
||||||
//I32SchemaViolation).
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
pub enum DataError {
|
pub enum DataError {
|
||||||
#[error("value does not exist for key: {0}")]
|
#[error("value does not exist for key: {0}")]
|
||||||
|
@ -47,7 +33,7 @@ pub enum DataError {
|
||||||
UnabortableTransactionError(#[from] UnabortableTransactionError),
|
UnabortableTransactionError(#[from] UnabortableTransactionError),
|
||||||
|
|
||||||
#[error("data migration error: {0}")]
|
#[error("data migration error: {0}")]
|
||||||
MigrationError(#[from] MigrationError),
|
MigrationError(#[from] super::migrator::MigrationError),
|
||||||
|
|
||||||
#[error("deserialization error: {0}")]
|
#[error("deserialization error: {0}")]
|
||||||
DeserializationError(#[from] bincode::Error),
|
DeserializationError(#[from] bincode::Error),
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
use refinery::include_migration_mods;
|
||||||
|
include_migration_mods!("src/db/sqlite/migrator/migrations");
|
|
@ -9,6 +9,7 @@ use std::str::FromStr;
|
||||||
use crate::models::RoomInfo;
|
use crate::models::RoomInfo;
|
||||||
|
|
||||||
pub mod errors;
|
pub mod errors;
|
||||||
|
pub mod migrator;
|
||||||
pub mod rooms;
|
pub mod rooms;
|
||||||
pub mod state;
|
pub mod state;
|
||||||
pub mod variables;
|
pub mod variables;
|
||||||
|
@ -93,6 +94,9 @@ impl Database {
|
||||||
|
|
||||||
drop(conn);
|
drop(conn);
|
||||||
|
|
||||||
|
//Migrate database.
|
||||||
|
migrator::migrate(&path).await?;
|
||||||
|
|
||||||
//Return actual conncetion pool.
|
//Return actual conncetion pool.
|
||||||
let conn = SqlitePoolOptions::new()
|
let conn = SqlitePoolOptions::new()
|
||||||
.max_connections(5)
|
.max_connections(5)
|
||||||
|
@ -101,10 +105,6 @@ impl Database {
|
||||||
|
|
||||||
Self::new_db(conn)
|
Self::new_db(conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn new_temp() -> Result<Database, DataError> {
|
|
||||||
Self::new("sqlite::memory:").await
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Clone for Database {
|
impl Clone for Database {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::config::ConfigError;
|
use crate::config::ConfigError;
|
||||||
use crate::db::errors::DataError;
|
use crate::db::errors::DataError;
|
||||||
use crate::{commands::CommandError, migrator::migrations};
|
use crate::{commands::CommandError, db::sqlite::migrator};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
|
@ -77,7 +77,7 @@ pub enum BotError {
|
||||||
DatabaseError(#[from] sled::Error),
|
DatabaseError(#[from] sled::Error),
|
||||||
|
|
||||||
#[error("database migration error: {0}")]
|
#[error("database migration error: {0}")]
|
||||||
SqliteError(#[from] crate::migrator::MigrationError),
|
SqliteError(#[from] migrator::MigrationError),
|
||||||
|
|
||||||
#[error("too many commands or message was too large")]
|
#[error("too many commands or message was too large")]
|
||||||
MessageTooLarge,
|
MessageTooLarge,
|
||||||
|
|
|
@ -11,7 +11,6 @@ pub mod error;
|
||||||
mod help;
|
mod help;
|
||||||
pub mod logic;
|
pub mod logic;
|
||||||
pub mod matrix;
|
pub mod matrix;
|
||||||
pub mod migrator;
|
|
||||||
pub mod models;
|
pub mod models;
|
||||||
mod parser;
|
mod parser;
|
||||||
pub mod state;
|
pub mod state;
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use std::env;
|
use std::env;
|
||||||
|
use tenebrous_dicebot::db::sqlite::migrator;
|
||||||
pub mod migrator;
|
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), migrator::MigrationError> {
|
async fn main() -> Result<(), migrator::MigrationError> {
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
use refinery::include_migration_mods;
|
|
||||||
include_migration_mods!("src/migrator/migrations");
|
|
Loading…
Reference in New Issue