mirror of
https://gitlab.computer.surgery/matrix/grapevine.git
synced 2025-12-17 07:41:23 +01:00
make load_or_create *only* load_or_create
Extracted the other logic to its current singular callsite for now. The load_or_create function finally does nothing other than load or create the database (and do some related checks, which is fine). This paves the way for more/better database surgery tooling.
This commit is contained in:
parent
e9caf228b3
commit
c2c6083277
3 changed files with 56 additions and 52 deletions
|
|
@ -40,11 +40,14 @@ use crate::{
|
||||||
ruma_wrapper::{Ar, Ra},
|
ruma_wrapper::{Ar, Ra},
|
||||||
server_server, well_known,
|
server_server, well_known,
|
||||||
},
|
},
|
||||||
config,
|
config::{self, Config, ListenComponent, ListenTransport},
|
||||||
config::{Config, ListenComponent, ListenTransport},
|
|
||||||
database::KeyValueDatabase,
|
database::KeyValueDatabase,
|
||||||
error, observability, services, utils,
|
error, observability, services,
|
||||||
utils::error::{Error, Result},
|
utils::{
|
||||||
|
self,
|
||||||
|
error::{Error, Result},
|
||||||
|
},
|
||||||
|
Services, SERVICES,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(crate) async fn run(args: ServeArgs) -> Result<(), error::ServeCommand> {
|
pub(crate) async fn run(args: ServeArgs) -> Result<(), error::ServeCommand> {
|
||||||
|
|
@ -70,8 +73,27 @@ pub(crate) async fn run(args: ServeArgs) -> Result<(), error::ServeCommand> {
|
||||||
.expect("should be able to increase the soft limit to the hard limit");
|
.expect("should be able to increase the soft limit to the hard limit");
|
||||||
|
|
||||||
info!("Loading database");
|
info!("Loading database");
|
||||||
let db = KeyValueDatabase::load_or_create(config, reload_handles)
|
let db = Box::leak(Box::new(
|
||||||
.map_err(Error::DatabaseError)?;
|
KeyValueDatabase::load_or_create(&config)
|
||||||
|
.map_err(Error::DatabaseError)?,
|
||||||
|
));
|
||||||
|
|
||||||
|
// This is the first and only time we initialize the SERVICE static
|
||||||
|
*SERVICES.write().unwrap() = Some(Box::leak(Box::new(
|
||||||
|
Services::build(db, config, reload_handles)
|
||||||
|
.map_err(Error::InitializeServices)?,
|
||||||
|
)));
|
||||||
|
|
||||||
|
// Matrix resource ownership is based on the server name; changing it
|
||||||
|
// requires recreating the database from scratch. This check needs to be
|
||||||
|
// done before background tasks are started to avoid data races.
|
||||||
|
if services().users.count().map(|x| x > 0).map_err(Error::NonZeroUsers)? {
|
||||||
|
let admin_bot = services().globals.admin_bot_user_id.as_ref();
|
||||||
|
if !services().users.exists(admin_bot).map_err(Error::AdminBotExists)? {
|
||||||
|
return Err(Error::Renamed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
db.apply_migrations().await.map_err(Error::DatabaseError)?;
|
db.apply_migrations().await.map_err(Error::DatabaseError)?;
|
||||||
|
|
||||||
info!("Starting background tasks");
|
info!("Starting background tasks");
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@ use tracing::{debug, error, info, info_span, warn, Instrument};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
config::DatabaseBackend,
|
config::DatabaseBackend,
|
||||||
observability::FilterReloadHandles,
|
|
||||||
service::{
|
service::{
|
||||||
media::MediaFileKey,
|
media::MediaFileKey,
|
||||||
rooms::{
|
rooms::{
|
||||||
|
|
@ -33,7 +32,7 @@ use crate::{
|
||||||
timeline::PduCount,
|
timeline::PduCount,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
services, utils, Config, Error, PduEvent, Result, Services, SERVICES,
|
services, utils, Config, Error, PduEvent, Result,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(crate) struct KeyValueDatabase {
|
pub(crate) struct KeyValueDatabase {
|
||||||
|
|
@ -319,11 +318,8 @@ impl KeyValueDatabase {
|
||||||
allow(unreachable_code)
|
allow(unreachable_code)
|
||||||
)]
|
)]
|
||||||
#[allow(clippy::too_many_lines)]
|
#[allow(clippy::too_many_lines)]
|
||||||
pub(crate) fn load_or_create(
|
pub(crate) fn load_or_create(config: &Config) -> Result<KeyValueDatabase> {
|
||||||
config: Config,
|
Self::check_db_setup(config)?;
|
||||||
reload_handles: FilterReloadHandles,
|
|
||||||
) -> Result<&'static KeyValueDatabase> {
|
|
||||||
Self::check_db_setup(&config)?;
|
|
||||||
|
|
||||||
if !Path::new(&config.database.path).exists() {
|
if !Path::new(&config.database.path).exists() {
|
||||||
fs::create_dir_all(&config.database.path).map_err(|_| {
|
fs::create_dir_all(&config.database.path).map_err(|_| {
|
||||||
|
|
@ -339,21 +335,19 @@ impl KeyValueDatabase {
|
||||||
not(any(feature = "rocksdb", feature = "sqlite")),
|
not(any(feature = "rocksdb", feature = "sqlite")),
|
||||||
allow(unused_variables)
|
allow(unused_variables)
|
||||||
)]
|
)]
|
||||||
let builder: Arc<dyn KeyValueDatabaseEngine> = match config
|
let builder: Arc<dyn KeyValueDatabaseEngine> =
|
||||||
.database
|
match config.database.backend {
|
||||||
.backend
|
|
||||||
{
|
|
||||||
#[cfg(feature = "sqlite")]
|
#[cfg(feature = "sqlite")]
|
||||||
DatabaseBackend::Sqlite => {
|
DatabaseBackend::Sqlite => {
|
||||||
Arc::new(Arc::<abstraction::sqlite::Engine>::open(&config)?)
|
Arc::new(Arc::<abstraction::sqlite::Engine>::open(config)?)
|
||||||
}
|
}
|
||||||
#[cfg(feature = "rocksdb")]
|
#[cfg(feature = "rocksdb")]
|
||||||
DatabaseBackend::Rocksdb => {
|
DatabaseBackend::Rocksdb => {
|
||||||
Arc::new(Arc::<abstraction::rocksdb::Engine>::open(&config)?)
|
Arc::new(Arc::<abstraction::rocksdb::Engine>::open(config)?)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let db_raw = Box::new(Self {
|
let db = Self {
|
||||||
db: builder.clone(),
|
db: builder.clone(),
|
||||||
userid_password: builder.open_tree("userid_password")?,
|
userid_password: builder.open_tree("userid_password")?,
|
||||||
userid_displayname: builder.open_tree("userid_displayname")?,
|
userid_displayname: builder.open_tree("userid_displayname")?,
|
||||||
|
|
@ -527,31 +521,7 @@ impl KeyValueDatabase {
|
||||||
our_real_users_cache: RwLock::new(HashMap::new()),
|
our_real_users_cache: RwLock::new(HashMap::new()),
|
||||||
appservice_in_room_cache: RwLock::new(HashMap::new()),
|
appservice_in_room_cache: RwLock::new(HashMap::new()),
|
||||||
lasttimelinecount_cache: Mutex::new(HashMap::new()),
|
lasttimelinecount_cache: Mutex::new(HashMap::new()),
|
||||||
});
|
};
|
||||||
|
|
||||||
let db = Box::leak(db_raw);
|
|
||||||
|
|
||||||
let services_raw =
|
|
||||||
Box::new(Services::build(db, config, reload_handles)?);
|
|
||||||
|
|
||||||
// This is the first and only time we initialize the SERVICE static
|
|
||||||
*SERVICES.write().unwrap() = Some(Box::leak(services_raw));
|
|
||||||
|
|
||||||
// Matrix resource ownership is based on the server name; changing it
|
|
||||||
// requires recreating the database from scratch.
|
|
||||||
if services().users.count()? > 0 {
|
|
||||||
let admin_bot = services().globals.admin_bot_user_id.as_ref();
|
|
||||||
if !services().users.exists(admin_bot)? {
|
|
||||||
error!(
|
|
||||||
user_id = %admin_bot,
|
|
||||||
"The admin bot does not exist and the database is not new",
|
|
||||||
);
|
|
||||||
return Err(Error::bad_database(
|
|
||||||
"Cannot reuse an existing database after changing the \
|
|
||||||
server name, please delete the old one first.",
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(db)
|
Ok(db)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
12
src/error.rs
12
src/error.rs
|
|
@ -61,6 +61,18 @@ pub(crate) enum ServeCommand {
|
||||||
|
|
||||||
#[error("failed to serve requests")]
|
#[error("failed to serve requests")]
|
||||||
Serve(#[from] Serve),
|
Serve(#[from] Serve),
|
||||||
|
|
||||||
|
#[error("failed to initialize services")]
|
||||||
|
InitializeServices(#[source] crate::utils::error::Error),
|
||||||
|
|
||||||
|
#[error("failed to check if there are any users")]
|
||||||
|
NonZeroUsers(#[source] crate::utils::error::Error),
|
||||||
|
|
||||||
|
#[error("failed to check if the admin bot exists")]
|
||||||
|
AdminBotExists(#[source] crate::utils::error::Error),
|
||||||
|
|
||||||
|
#[error("`server_name` in the database and config file differ")]
|
||||||
|
Renamed,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Observability initialization errors
|
/// Observability initialization errors
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue