refactor: minimum implementation of revolt-models and revolt-database
This commit is contained in:
22
crates/core/database/Cargo.toml
Normal file
22
crates/core/database/Cargo.toml
Normal file
@@ -0,0 +1,22 @@
|
||||
[package]
|
||||
name = "revolt-database"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[features]
|
||||
mongodb = [ "dep:mongodb" ]
|
||||
default = [ "mongodb" ]
|
||||
|
||||
[dependencies]
|
||||
# Serialisation
|
||||
serde_json = "1"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
|
||||
# Database
|
||||
mongodb = { optional = true, version = "2.1.0", default-features = false }
|
||||
|
||||
# Async Language Features
|
||||
futures = "0.3.19"
|
||||
async-recursion = "1.0.4"
|
||||
4
crates/core/database/src/drivers/dummy.rs
Normal file
4
crates/core/database/src/drivers/dummy.rs
Normal file
@@ -0,0 +1,4 @@
|
||||
database_derived!(
|
||||
/// Dummy implementation
|
||||
pub struct DummyDb {}
|
||||
);
|
||||
5
crates/core/database/src/drivers/mod.rs
Normal file
5
crates/core/database/src/drivers/mod.rs
Normal file
@@ -0,0 +1,5 @@
|
||||
mod dummy;
|
||||
mod mongodb;
|
||||
|
||||
pub use self::dummy::*;
|
||||
pub use self::mongodb::*;
|
||||
228
crates/core/database/src/drivers/mongodb.rs
Normal file
228
crates/core/database/src/drivers/mongodb.rs
Normal file
@@ -0,0 +1,228 @@
|
||||
use std::collections::HashMap;
|
||||
use std::ops::Deref;
|
||||
|
||||
use futures::StreamExt;
|
||||
use mongodb::bson::{doc, to_document, Document};
|
||||
use mongodb::error::Result;
|
||||
use mongodb::options::{FindOneOptions, FindOptions};
|
||||
use mongodb::results::{DeleteResult, InsertOneResult, UpdateResult};
|
||||
use serde::de::DeserializeOwned;
|
||||
use serde::Serialize;
|
||||
|
||||
database_derived!(
|
||||
#[cfg(feature = "mongodb")]
|
||||
/// MongoDB implementation
|
||||
pub struct MongoDb(pub ::mongodb::Client);
|
||||
);
|
||||
|
||||
impl Deref for MongoDb {
|
||||
type Target = mongodb::Client;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl MongoDb {
|
||||
/// Get the Revolt database
|
||||
pub fn db(&self) -> mongodb::Database {
|
||||
self.database("revolt")
|
||||
}
|
||||
|
||||
/// Get a collection by its name
|
||||
pub fn col<T>(&self, collection: &str) -> mongodb::Collection<T> {
|
||||
self.db().collection(collection)
|
||||
}
|
||||
|
||||
/// Insert one document into a collection
|
||||
async fn insert_one<T: Serialize>(
|
||||
&self,
|
||||
collection: &'static str,
|
||||
document: T,
|
||||
) -> Result<InsertOneResult> {
|
||||
self.col::<T>(collection).insert_one(document, None).await
|
||||
}
|
||||
|
||||
/// Find multiple documents in a collection with options
|
||||
async fn find_with_options<O, T: DeserializeOwned + Unpin + Send + Sync>(
|
||||
&self,
|
||||
collection: &'static str,
|
||||
projection: Document,
|
||||
options: O,
|
||||
) -> Result<Vec<T>>
|
||||
where
|
||||
O: Into<Option<FindOptions>>,
|
||||
{
|
||||
Ok(self
|
||||
.col::<T>(collection)
|
||||
.find(projection, options)
|
||||
.await?
|
||||
.filter_map(|s| async {
|
||||
if cfg!(debug_assertions) {
|
||||
// Hard fail on invalid documents
|
||||
Some(s.unwrap())
|
||||
} else {
|
||||
s.ok()
|
||||
}
|
||||
})
|
||||
.collect::<Vec<T>>()
|
||||
.await)
|
||||
}
|
||||
|
||||
/// Find multiple documents in a collection
|
||||
async fn find<T: DeserializeOwned + Unpin + Send + Sync>(
|
||||
&self,
|
||||
collection: &'static str,
|
||||
projection: Document,
|
||||
) -> Result<Vec<T>> {
|
||||
self.find_with_options(collection, projection, None).await
|
||||
}
|
||||
|
||||
/// Find one document with options
|
||||
async fn find_one_with_options<O, T: DeserializeOwned + Unpin + Send + Sync>(
|
||||
&self,
|
||||
collection: &'static str,
|
||||
projection: Document,
|
||||
options: O,
|
||||
) -> Result<Option<T>>
|
||||
where
|
||||
O: Into<Option<FindOneOptions>>,
|
||||
{
|
||||
self.col::<T>(collection)
|
||||
.find_one(projection, options)
|
||||
.await
|
||||
}
|
||||
|
||||
/// Find one document
|
||||
async fn find_one<T: DeserializeOwned + Unpin + Send + Sync>(
|
||||
&self,
|
||||
collection: &'static str,
|
||||
projection: Document,
|
||||
) -> Result<Option<T>> {
|
||||
self.find_one_with_options(collection, projection, None)
|
||||
.await
|
||||
}
|
||||
|
||||
/// Find one document by its ID
|
||||
async fn find_one_by_id<T: DeserializeOwned + Unpin + Send + Sync>(
|
||||
&self,
|
||||
collection: &'static str,
|
||||
id: &str,
|
||||
) -> Result<Option<T>> {
|
||||
self.find_one(
|
||||
collection,
|
||||
doc! {
|
||||
"_id": id
|
||||
},
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
/// Update one document given a projection, partial document, and list of paths to unset
|
||||
async fn update_one<P, T: Serialize>(
|
||||
&self,
|
||||
collection: &'static str,
|
||||
projection: Document,
|
||||
partial: T,
|
||||
remove: Vec<&dyn IntoDocumentPath>,
|
||||
prefix: P,
|
||||
) -> Result<UpdateResult>
|
||||
where
|
||||
P: Into<Option<String>>,
|
||||
{
|
||||
let prefix = prefix.into();
|
||||
|
||||
let mut unset = doc! {};
|
||||
for field in remove {
|
||||
if let Some(path) = field.as_path() {
|
||||
if let Some(prefix) = &prefix {
|
||||
unset.insert(prefix.to_owned() + path, 1_i32);
|
||||
} else {
|
||||
unset.insert(path, 1_i32);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let query = doc! {
|
||||
"$unset": unset,
|
||||
"$set": if let Some(prefix) = &prefix {
|
||||
to_document(&prefix_keys(&partial, prefix))
|
||||
} else {
|
||||
to_document(&partial)
|
||||
}?
|
||||
};
|
||||
|
||||
self.col::<Document>(collection)
|
||||
.update_one(projection, query, None)
|
||||
.await
|
||||
}
|
||||
|
||||
/// Update one document given an ID, partial document, and list of paths to unset
|
||||
async fn update_one_by_id<P, T: Serialize>(
|
||||
&self,
|
||||
collection: &'static str,
|
||||
id: &str,
|
||||
partial: T,
|
||||
remove: Vec<&dyn IntoDocumentPath>,
|
||||
prefix: P,
|
||||
) -> Result<UpdateResult>
|
||||
where
|
||||
P: Into<Option<String>>,
|
||||
{
|
||||
self.update_one(
|
||||
collection,
|
||||
doc! {
|
||||
"_id": id
|
||||
},
|
||||
partial,
|
||||
remove,
|
||||
prefix,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
/// Delete one document by the given projection
|
||||
async fn delete_one(
|
||||
&self,
|
||||
collection: &'static str,
|
||||
projection: Document,
|
||||
) -> Result<DeleteResult> {
|
||||
self.col::<Document>(collection)
|
||||
.delete_one(projection, None)
|
||||
.await
|
||||
}
|
||||
|
||||
/// Delete one document by the given ID
|
||||
async fn delete_one_by_id(&self, collection: &'static str, id: &str) -> Result<DeleteResult> {
|
||||
self.delete_one(
|
||||
collection,
|
||||
doc! {
|
||||
"_id": id
|
||||
},
|
||||
)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
/// Just a string ID struct
|
||||
#[derive(Deserialize)]
|
||||
pub struct DocumentId {
|
||||
#[serde(rename = "_id")]
|
||||
pub id: String,
|
||||
}
|
||||
|
||||
pub trait IntoDocumentPath: Send + Sync {
|
||||
/// Create JSON key path
|
||||
fn as_path(&self) -> Option<&'static str>;
|
||||
}
|
||||
|
||||
/// Prefix keys on an arbitrary object
|
||||
pub fn prefix_keys<T: Serialize>(t: &T, prefix: &str) -> HashMap<String, serde_json::Value> {
|
||||
let v: String = serde_json::to_string(t).unwrap();
|
||||
let v: HashMap<String, serde_json::Value> = serde_json::from_str(&v).unwrap();
|
||||
v.into_iter()
|
||||
.filter(|(_k, v)| !v.is_null())
|
||||
.map(|(k, v)| (prefix.to_owned() + &k, v))
|
||||
.collect()
|
||||
}
|
||||
66
crates/core/database/src/lib.rs
Normal file
66
crates/core/database/src/lib.rs
Normal file
@@ -0,0 +1,66 @@
|
||||
#[macro_use]
|
||||
extern crate serde;
|
||||
|
||||
#[macro_use]
|
||||
extern crate async_recursion;
|
||||
|
||||
macro_rules! database_derived {
|
||||
( $( $item:item )+ ) => {
|
||||
$(
|
||||
#[derive(Clone)]
|
||||
$item
|
||||
)+
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(feature = "mongodb")]
|
||||
pub use mongodb;
|
||||
|
||||
mod drivers;
|
||||
pub use drivers::*;
|
||||
|
||||
/// Database information to use to create a client
|
||||
pub enum DatabaseInfo {
|
||||
/// Auto-detect the database in use
|
||||
Auto,
|
||||
/// Use the mock database
|
||||
Dummy,
|
||||
/// Connect to MongoDB
|
||||
MongoDb(String),
|
||||
/// Use existing MongoDB connection
|
||||
MongoDbFromClient(::mongodb::Client),
|
||||
}
|
||||
|
||||
/// Database
|
||||
#[derive(Clone)]
|
||||
pub enum Database {
|
||||
/// Mock database
|
||||
Dummy(DummyDb),
|
||||
/// MongoDB database
|
||||
MongoDb(MongoDb),
|
||||
}
|
||||
|
||||
impl DatabaseInfo {
|
||||
/// Create a database client from the given database information
|
||||
#[async_recursion]
|
||||
pub async fn connect(self) -> Result<Database, String> {
|
||||
Ok(match self {
|
||||
DatabaseInfo::Auto => {
|
||||
if let Ok(uri) = std::env::var("MONGODB") {
|
||||
return DatabaseInfo::MongoDb(uri).connect().await;
|
||||
}
|
||||
|
||||
DatabaseInfo::Dummy.connect().await?
|
||||
}
|
||||
DatabaseInfo::Dummy => Database::Dummy(DummyDb {}),
|
||||
DatabaseInfo::MongoDb(uri) => {
|
||||
let client = mongodb::Client::with_uri_str(uri)
|
||||
.await
|
||||
.map_err(|_| "Failed to init db connection.".to_string())?;
|
||||
|
||||
Database::MongoDb(MongoDb(client))
|
||||
}
|
||||
DatabaseInfo::MongoDbFromClient(client) => Database::MongoDb(MongoDb(client)),
|
||||
})
|
||||
}
|
||||
}
|
||||
33
crates/core/models/Cargo.toml
Normal file
33
crates/core/models/Cargo.toml
Normal file
@@ -0,0 +1,33 @@
|
||||
[package]
|
||||
name = "revolt-models"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[features]
|
||||
serde = [ "dep:serde" ]
|
||||
async-std-runtime = [ "async-std" ]
|
||||
database = [ "revolt-database", "revolt-database/default", "authifier/database-mongodb" ]
|
||||
|
||||
default = [ "serde", "async-std-runtime", "database" ]
|
||||
|
||||
[dependencies]
|
||||
# Utility
|
||||
log = "*"
|
||||
|
||||
# Serialisation
|
||||
serde = { version = "1", features = ["derive"], optional = true }
|
||||
|
||||
# Async Language Features
|
||||
futures = "0.3.19"
|
||||
async-trait = "0.1.51"
|
||||
|
||||
# Async
|
||||
async-std = { version = "1.8.0", features = ["attributes"], optional = true }
|
||||
|
||||
# Peer dependencies
|
||||
revolt-database = { path = "../database", optional = true, default-features = false }
|
||||
|
||||
# Authifier
|
||||
authifier = { version = "1.0", default-features = false }
|
||||
8
crates/core/models/examples/migrate.rs
Normal file
8
crates/core/models/examples/migrate.rs
Normal file
@@ -0,0 +1,8 @@
|
||||
use revolt_database::DatabaseInfo;
|
||||
use revolt_models::*;
|
||||
|
||||
#[async_std::main]
|
||||
async fn main() {
|
||||
let db = Database(DatabaseInfo::Auto.connect().await.unwrap());
|
||||
db.migrate_database().await.unwrap();
|
||||
}
|
||||
9
crates/core/models/src/admin_migrations/mod.rs
Normal file
9
crates/core/models/src/admin_migrations/mod.rs
Normal file
@@ -0,0 +1,9 @@
|
||||
mod model;
|
||||
|
||||
pub use model::*;
|
||||
|
||||
#[cfg(feature = "database")]
|
||||
mod ops;
|
||||
|
||||
#[cfg(feature = "database")]
|
||||
pub use ops::*;
|
||||
10
crates/core/models/src/admin_migrations/model.rs
Normal file
10
crates/core/models/src/admin_migrations/model.rs
Normal file
@@ -0,0 +1,10 @@
|
||||
auto_derived!(
|
||||
/// Document representing migration information
|
||||
pub struct MigrationInfo {
|
||||
/// Unique Id
|
||||
#[serde(rename = "_id")]
|
||||
pub id: i32,
|
||||
/// Current database revision
|
||||
pub revision: i32,
|
||||
}
|
||||
);
|
||||
11
crates/core/models/src/admin_migrations/ops/dummy.rs
Normal file
11
crates/core/models/src/admin_migrations/ops/dummy.rs
Normal file
@@ -0,0 +1,11 @@
|
||||
use revolt_database::DummyDb;
|
||||
|
||||
use super::AbstractMigrations;
|
||||
|
||||
#[async_trait]
|
||||
impl AbstractMigrations for DummyDb {
|
||||
/// Migrate the database
|
||||
async fn migrate_database(&self) -> Result<(), ()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
8
crates/core/models/src/admin_migrations/ops/mod.rs
Normal file
8
crates/core/models/src/admin_migrations/ops/mod.rs
Normal file
@@ -0,0 +1,8 @@
|
||||
mod dummy;
|
||||
mod mongodb;
|
||||
|
||||
#[async_trait]
|
||||
pub trait AbstractMigrations: Sync + Send {
|
||||
/// Migrate the database
|
||||
async fn migrate_database(&self) -> Result<(), ()>;
|
||||
}
|
||||
@@ -1,13 +1,14 @@
|
||||
use crate::{AbstractMigrations, Result};
|
||||
use revolt_database::MongoDb;
|
||||
|
||||
use super::super::MongoDb;
|
||||
use super::AbstractMigrations;
|
||||
|
||||
mod init;
|
||||
mod scripts;
|
||||
|
||||
#[async_trait]
|
||||
impl AbstractMigrations for MongoDb {
|
||||
async fn migrate_database(&self) -> Result<()> {
|
||||
/// Migrate the database
|
||||
async fn migrate_database(&self) -> Result<(), ()> {
|
||||
info!("Migrating the database.");
|
||||
|
||||
let list = self
|
||||
@@ -1,9 +1,8 @@
|
||||
use crate::r#impl::mongo::MongoDb;
|
||||
|
||||
use super::scripts::LATEST_REVISION;
|
||||
|
||||
use mongodb::bson::doc;
|
||||
use mongodb::options::CreateCollectionOptions;
|
||||
use revolt_database::mongodb::bson::doc;
|
||||
use revolt_database::mongodb::options::CreateCollectionOptions;
|
||||
use revolt_database::MongoDb;
|
||||
|
||||
pub async fn create_database(db: &MongoDb) {
|
||||
info!("Creating database.");
|
||||
@@ -1,15 +1,15 @@
|
||||
use std::{time::Duration, ops::BitXor};
|
||||
use std::{ops::BitXor, time::Duration};
|
||||
|
||||
use bson::{Bson, DateTime};
|
||||
use futures::StreamExt;
|
||||
use mongodb::{
|
||||
bson::{doc, from_bson, from_document, to_document, Document},
|
||||
options::FindOptions,
|
||||
use revolt_database::{
|
||||
mongodb::{
|
||||
bson::{doc, from_bson, from_document, to_document, Bson, DateTime, Document},
|
||||
options::FindOptions,
|
||||
},
|
||||
MongoDb,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{r#impl::mongo::MongoDb, Permission, DEFAULT_PERMISSION_SERVER};
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct MigrationInfo {
|
||||
_id: i32,
|
||||
@@ -504,7 +504,7 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 {
|
||||
update.insert(
|
||||
"default_permissions",
|
||||
// Remove Send Message permission if it wasn't originally granted
|
||||
DEFAULT_PERMISSION_SERVER.bitxor(if has_send { 0 } else { Permission::SendMessage as u64}) as i64,
|
||||
(4000323584).bitxor(if has_send { 0 } else { (1 << 22) as u64 }) as i64,
|
||||
);
|
||||
|
||||
if let Some(Bson::Document(mut roles)) = document.remove("roles") {
|
||||
@@ -563,7 +563,7 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 {
|
||||
doc! {
|
||||
"default_permissions": {
|
||||
"a": 0_i64,
|
||||
"d": Permission::SendMessage as i64
|
||||
"d": (1 << 22) as i64
|
||||
}
|
||||
},
|
||||
);
|
||||
40
crates/core/models/src/lib.rs
Normal file
40
crates/core/models/src/lib.rs
Normal file
@@ -0,0 +1,40 @@
|
||||
#[cfg(feature = "serde")]
|
||||
#[macro_use]
|
||||
extern crate serde;
|
||||
|
||||
#[macro_use]
|
||||
extern crate async_trait;
|
||||
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
|
||||
macro_rules! auto_derived {
|
||||
( $( $item:item )+ ) => {
|
||||
$(
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
#[derive(Debug, Clone)]
|
||||
$item
|
||||
)+
|
||||
};
|
||||
}
|
||||
|
||||
mod admin_migrations;
|
||||
|
||||
pub use admin_migrations::*;
|
||||
|
||||
pub struct Database(pub revolt_database::Database);
|
||||
|
||||
pub trait AbstractDatabase: Sync + Send + admin_migrations::AbstractMigrations {}
|
||||
impl AbstractDatabase for revolt_database::DummyDb {}
|
||||
impl AbstractDatabase for revolt_database::MongoDb {}
|
||||
|
||||
impl std::ops::Deref for Database {
|
||||
type Target = dyn AbstractDatabase;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
match &self.0 {
|
||||
revolt_database::Database::Dummy(dummy) => dummy,
|
||||
revolt_database::Database::MongoDb(mongo) => mongo,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -55,5 +55,9 @@ revolt_rocket_okapi = { version = "0.9.1", features = [ "swagger" ] }
|
||||
# quark
|
||||
revolt-quark = { path = "../quark" }
|
||||
|
||||
# core
|
||||
revolt-database = { path = "../core/database" }
|
||||
revolt-models = { path = "../core/models" }
|
||||
|
||||
[build-dependencies]
|
||||
vergen = "7.5.0"
|
||||
|
||||
@@ -22,15 +22,19 @@ async fn rocket() -> _ {
|
||||
revolt_quark::variables::delta::preflight_checks();
|
||||
|
||||
// Setup database
|
||||
let db = DatabaseInfo::Auto.connect().await.unwrap();
|
||||
let db = revolt_database::DatabaseInfo::Auto.connect().await.unwrap();
|
||||
let db = revolt_models::Database(db);
|
||||
db.migrate_database().await.unwrap();
|
||||
|
||||
// Legacy database setup from quark
|
||||
let legacy_db = DatabaseInfo::Auto.connect().await.unwrap();
|
||||
|
||||
// Setup Authifier event channel
|
||||
let (sender, receiver) = unbounded();
|
||||
|
||||
// Setup Authifier
|
||||
let authifier = Authifier {
|
||||
database: db.clone().into(),
|
||||
database: legacy_db.clone().into(),
|
||||
config: revolt_quark::util::authifier::config(),
|
||||
event_channel: Some(sender),
|
||||
};
|
||||
@@ -52,7 +56,7 @@ async fn rocket() -> _ {
|
||||
});
|
||||
|
||||
// Launch background task workers
|
||||
async_std::task::spawn(revolt_quark::tasks::start_workers(db.clone()));
|
||||
async_std::task::spawn(revolt_quark::tasks::start_workers(legacy_db.clone()));
|
||||
|
||||
// Configure CORS
|
||||
let cors = revolt_quark::web::cors::new();
|
||||
@@ -65,6 +69,7 @@ async fn rocket() -> _ {
|
||||
.mount("/swagger/", revolt_quark::web::swagger::routes())
|
||||
.manage(authifier)
|
||||
.manage(db)
|
||||
.manage(legacy_db)
|
||||
.manage(cors.clone())
|
||||
.attach(revolt_quark::web::ratelimiter::RatelimitFairing)
|
||||
.attach(cors)
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
use crate::{AbstractMigrations, Result};
|
||||
|
||||
use super::super::DummyDb;
|
||||
|
||||
#[async_trait]
|
||||
impl AbstractMigrations for DummyDb {
|
||||
async fn migrate_database(&self) -> Result<()> {
|
||||
info!("Migrating the database.");
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
use crate::AbstractDatabase;
|
||||
|
||||
pub mod admin {
|
||||
pub mod migrations;
|
||||
pub mod stats;
|
||||
}
|
||||
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
//! Database agnostic implementations.
|
||||
|
||||
pub mod admin {
|
||||
pub mod migrations;
|
||||
}
|
||||
|
||||
pub mod media {
|
||||
pub mod attachment;
|
||||
pub mod emoji;
|
||||
|
||||
@@ -12,7 +12,6 @@ use serde::{Deserialize, Serialize};
|
||||
use crate::{util::manipulation::prefix_keys, AbstractDatabase, Error, Result};
|
||||
|
||||
pub mod admin {
|
||||
pub mod migrations;
|
||||
pub mod stats;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// Document representing migration information
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct MigrationInfo {
|
||||
/// Unique Id
|
||||
#[serde(rename = "_id")]
|
||||
id: i32,
|
||||
/// Current database revision
|
||||
revision: i32,
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
mod admin {
|
||||
pub mod migrations;
|
||||
pub mod simple;
|
||||
pub mod stats;
|
||||
}
|
||||
@@ -47,7 +46,6 @@ pub use channel_invite::Invite;
|
||||
pub use channel_unread::ChannelUnread;
|
||||
pub use emoji::Emoji;
|
||||
pub use message::Message;
|
||||
pub use migrations::MigrationInfo;
|
||||
pub use report::Report;
|
||||
pub use server::Server;
|
||||
pub use server_ban::ServerBan;
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
use crate::Result;
|
||||
|
||||
#[async_trait]
|
||||
pub trait AbstractMigrations: Sync + Send {
|
||||
async fn migrate_database(&self) -> Result<()>;
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
mod admin {
|
||||
pub mod migrations;
|
||||
pub mod stats;
|
||||
}
|
||||
|
||||
@@ -32,7 +31,6 @@ mod safety {
|
||||
pub mod snapshot;
|
||||
}
|
||||
|
||||
pub use admin::migrations::AbstractMigrations;
|
||||
pub use admin::stats::AbstractStats;
|
||||
|
||||
pub use media::attachment::AbstractAttachment;
|
||||
@@ -57,7 +55,6 @@ pub use safety::snapshot::AbstractSnapshot;
|
||||
pub trait AbstractDatabase:
|
||||
Sync
|
||||
+ Send
|
||||
+ AbstractMigrations
|
||||
+ AbstractStats
|
||||
+ AbstractAttachment
|
||||
+ AbstractEmoji
|
||||
|
||||
Reference in New Issue
Block a user