Skip to content

Commit

Permalink
Separate the global location of files per OS & create a configuration…
Browse files Browse the repository at this point in the history
… trait to read them (#171)

* Install from source instructions

* Improved comment

* Separate the global location of files per OS & create a configuration trait to read them

---------

Co-authored-by: Boppy <no-reply@boppygames.gg>
  • Loading branch information
mamcx and Boppy authored Aug 22, 2023
1 parent 66a8f22 commit 68b9536
Show file tree
Hide file tree
Showing 11 changed files with 243 additions and 22 deletions.
39 changes: 39 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ serde = "1.0.136"
serde_json = { version = "1.0.87", features = ["raw_value"] }
serde_path_to_error = "0.1.9"
serde_with = { version = "2.2.0", features = ["base64", "hex"] }
serial_test = "2.0.0"
sha1 = "0.10.1"
sha3 = "0.10.0"
slab = "0.4.7"
Expand Down
154 changes: 154 additions & 0 deletions crates/core/src/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
use std::env::temp_dir;
use std::path::{Path, PathBuf};

#[cfg(not(any(target_os = "macos", target_os = "windows")))]
mod paths {
use super::*;

/// The default path for the database files.
pub(super) fn db_path() -> PathBuf {
PathBuf::from("/stdb")
}

/// The default path for the database logs.
pub(super) fn logs_path() -> PathBuf {
PathBuf::from("/var/log")
}

/// The default path for the database config files.
pub(super) fn config_path() -> PathBuf {
PathBuf::from("/etc/spacetimedb/")
}
}

#[cfg(target_os = "macos")]
mod paths {
use super::*;

/// The default path for the database files.
pub(super) fn db_path() -> PathBuf {
PathBuf::from("/usr/local/var/stdb")
}

/// The default path for the database logs.
pub(super) fn logs_path() -> PathBuf {
PathBuf::from("/var/log")
}

/// The default path for the database config files.
pub(super) fn config_path() -> PathBuf {
PathBuf::from("/etc/spacetimedb/")
}
}

#[cfg(target_os = "windows")]
mod paths {
use super::*;

/// The default path for the database files.
pub(super) fn db_path() -> PathBuf {
dirs::data_dir()
.map(|x| x.join("stdb"))
.expect("failed to read the windows `data directory`")
}

/// The default path for the database logs.
pub(super) fn logs_path() -> PathBuf {
db_path().join("log")
}

/// The default path for the database config files.
pub(super) fn config_path() -> PathBuf {
dirs::config_dir()
.map(|x| x.join("stdb"))
.expect("Fail to read the windows `config directory`")
}
}

/// Returns the default path for the database in the `OS` temporary directory.
pub fn stdb_path_temp() -> PathBuf {
temp_dir().join("stdb")
}

/// Types specifying where to find various files needed by spacetimedb.
pub trait SpacetimeDbFiles {
/// The path for the database files.
fn db_path(&self) -> PathBuf;

/// The path for the database logs.
fn logs(&self) -> PathBuf;

/// The path for the database config files.
fn config(&self) -> PathBuf;

/// The path of the database config file `log.conf` for logs.
fn log_config(&self) -> PathBuf {
self.config().join("log.conf")
}

/// The path of the private key file `id_ecdsa`.
fn private_key(&self) -> PathBuf {
self.config().join("id_ecdsa")
}

/// The path of the public key file `id_ecdsa.pub`.
fn public_key(&self) -> PathBuf {
self.config().join("id_ecdsa.pub")
}
}

/// The location of paths for the database in a local OR temp folder.
pub struct FilesLocal {
dir: PathBuf,
}

impl FilesLocal {
/// Create a new [FilesLocal], appending `name` to the `temp` folder returned by [stdb_path_temp].
pub fn temp(name: &str) -> Self {
assert!(!name.is_empty(), "`name` should be filled");

Self {
dir: stdb_path_temp().join(name),
}
}

/// Create a new [FilesLocal] that is in a hidden `path + .spacetime` folder.
pub fn hidden<P: AsRef<Path>>(path: P) -> Self {
Self {
dir: path.as_ref().join(".spacetime"),
}
}
}

impl SpacetimeDbFiles for FilesLocal {
fn db_path(&self) -> PathBuf {
self.dir.clone()
}

fn logs(&self) -> PathBuf {
self.db_path().join("logs")
}

fn config(&self) -> PathBuf {
self.db_path().join("conf")
}
}

/// The global location of paths for the database.
///
/// NOTE: This location varies by OS.
pub struct FilesGlobal;

impl SpacetimeDbFiles for FilesGlobal {
fn db_path(&self) -> PathBuf {
paths::db_path()
}

fn logs(&self) -> PathBuf {
paths::logs_path()
}

fn config(&self) -> PathBuf {
paths::config_path()
}
}
2 changes: 1 addition & 1 deletion crates/core/src/database_logger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ impl DatabaseLogger {
let filepath = root.join("0.log");

// TODO: Read backwards from the end of the file to only read in the latest lines
let text = tokio::fs::read_to_string(&filepath).await.expect("reading file");
let text = tokio::fs::read_to_string(&filepath).await.expect("reading log file");

let Some(num_lines) = num_lines else { return text };

Expand Down
1 change: 1 addition & 0 deletions crates/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ pub mod protobuf {
pub use spacetimedb_client_api_messages::*;
}
pub mod client;
pub mod config;
pub mod control_db;
pub mod database_instance_context;
pub mod database_instance_context_controller;
Expand Down
27 changes: 15 additions & 12 deletions crates/standalone/src/subcommands/start.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use crate::util::{create_dir_or_err, create_file_with_contents};
use crate::StandaloneEnv;
use clap::ArgAction::SetTrue;
use clap::{Arg, ArgMatches};
use spacetimedb::config::{FilesGlobal, FilesLocal, SpacetimeDbFiles};
use spacetimedb::db::{db_metrics, Storage};
use spacetimedb::{startup, worker_metrics};
use std::net::TcpListener;
Expand Down Expand Up @@ -85,20 +86,22 @@ pub fn cli(mode: ProgramMode) -> clap::Command {
// The standalone mode instead uses global directories.
match mode {
ProgramMode::CLI => {
log_conf_path_arg = log_conf_path_arg.default_value(format!("{}/.spacetime/log.conf", default_root));
log_dir_path_arg = log_dir_path_arg.default_value(format!("{}/.spacetime", default_root));
database_path_arg = database_path_arg.default_value(format!("{}/.spacetime/stdb", default_root));
jwt_pub_key_path_arg =
jwt_pub_key_path_arg.default_value(format!("{}/.spacetime/id_ecdsa.pub", default_root));
jwt_priv_key_path_arg =
jwt_priv_key_path_arg.default_value(format!("{}/.spacetime/id_ecdsa", default_root));
let paths = FilesLocal::hidden(default_root);

log_conf_path_arg = log_conf_path_arg.default_value(paths.log_config().into_os_string());
log_dir_path_arg = log_dir_path_arg.default_value(paths.logs().into_os_string());
database_path_arg = database_path_arg.default_value(paths.db_path().into_os_string());
jwt_pub_key_path_arg = jwt_pub_key_path_arg.default_value(paths.public_key().into_os_string());
jwt_priv_key_path_arg = jwt_priv_key_path_arg.default_value(paths.private_key().into_os_string());
}
ProgramMode::Standalone => {
log_conf_path_arg = log_conf_path_arg.default_value("/etc/spacetimedb/log.conf");
log_dir_path_arg = log_dir_path_arg.default_value("/var/log");
database_path_arg = database_path_arg.default_value("/stdb");
jwt_pub_key_path_arg = jwt_pub_key_path_arg.default_value("/etc/spacetimedb/id_ecdsa.pub");
jwt_priv_key_path_arg = jwt_priv_key_path_arg.default_value("/etc/spacetimedb/id_ecdsa");
let paths = FilesGlobal;

log_conf_path_arg = log_conf_path_arg.default_value(paths.log_config().into_os_string());
log_dir_path_arg = log_dir_path_arg.default_value(paths.logs().into_os_string());
database_path_arg = database_path_arg.default_value(paths.db_path().into_os_string());
jwt_pub_key_path_arg = jwt_pub_key_path_arg.default_value(paths.public_key().into_os_string());
jwt_priv_key_path_arg = jwt_priv_key_path_arg.default_value(paths.private_key().into_os_string());
}
}

Expand Down
3 changes: 3 additions & 0 deletions crates/testing/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,6 @@ anyhow.workspace = true
serde_json.workspace = true
tokio.workspace = true
wasmbin.workspace = true

[dev-dependencies]
serial_test.workspace = true
16 changes: 8 additions & 8 deletions crates/testing/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
use spacetimedb::config::{FilesLocal, SpacetimeDbFiles};
use std::env;
use std::path::{Path, PathBuf};

pub mod modules;

pub fn set_key_env_vars() {
pub fn set_key_env_vars(paths: &FilesLocal) {
let set_if_not_exist = |var, path| {
if env::var_os(var).is_none() {
env::set_var(var, Path::new(env!("CARGO_MANIFEST_DIR")).join("../..").join(path));
env::set_var(var, path);
}
};

set_if_not_exist("STDB_PATH", PathBuf::from("/stdb"));
set_if_not_exist("SPACETIMEDB_LOGS_PATH", PathBuf::from("/var/log"));
set_if_not_exist("SPACETIMEDB_LOG_CONFIG", PathBuf::from("/stdb/log.conf"));
set_if_not_exist("SPACETIMEDB_JWT_PUB_KEY", PathBuf::from("/stdb/id_ecdsa.pub"));
set_if_not_exist("SPACETIMEDB_JWT_PRIV_KEY", PathBuf::from("/stdb/id_ecdsa"));
set_if_not_exist("STDB_PATH", paths.db_path());
set_if_not_exist("SPACETIMEDB_LOGS_PATH", paths.logs());
set_if_not_exist("SPACETIMEDB_LOG_CONFIG", paths.log_config());
set_if_not_exist("SPACETIMEDB_JWT_PUB_KEY", paths.public_key());
set_if_not_exist("SPACETIMEDB_JWT_PRIV_KEY", paths.private_key());
}
8 changes: 7 additions & 1 deletion crates/testing/src/modules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use spacetimedb::database_logger::DatabaseLogger;
use spacetimedb::db::Storage;
use spacetimedb::hash::hash_bytes;

use spacetimedb::config::{FilesLocal, SpacetimeDbFiles};
use spacetimedb::messages::control_db::HostType;
use spacetimedb_client_api::{ControlCtx, ControlStateDelegate, WorkerCtx};
use spacetimedb_standalone::StandaloneEnv;
Expand Down Expand Up @@ -129,7 +130,12 @@ pub async fn load_module(name: &str) -> ModuleHandle {
// exercise functionality like restarting the database.
let storage = Storage::Disk;

crate::set_key_env_vars();
let paths = FilesLocal::temp(name);
// The database created in the `temp` folder can't be randomized,
// so it persists after running the test.
std::fs::remove_dir(paths.db_path()).ok();

crate::set_key_env_vars(&paths);
let env = spacetimedb_standalone::StandaloneEnv::init(storage).await.unwrap();
let identity = env.control_db().alloc_spacetime_identity().await.unwrap();
let address = env.control_db().alloc_spacetime_address().await.unwrap();
Expand Down
6 changes: 6 additions & 0 deletions crates/testing/tests/standalone_integration_test.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
use serde_json::Value;
use serial_test::serial;
use spacetimedb_testing::modules::{compile, with_module_async};

// The tests MUST be run in sequence because they read the OS environment
// and can cause a race when run in parallel.

#[test]
#[serial]
fn test_calling_a_reducer() {
compile("spacetimedb-quickstart");
with_module_async("spacetimedb-quickstart", |module| async move {
Expand All @@ -23,6 +28,7 @@ fn test_calling_a_reducer() {
}

#[test]
#[serial]
fn test_calling_a_reducer_with_private_table() {
compile("rust-wasm-test");
with_module_async("rust-wasm-test", |module| async move {
Expand Down
8 changes: 8 additions & 0 deletions run_standalone.sh → run_standalone_temp.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/bin/bash
# Run a ephemeral database inside a `temp` folder
set -euo pipefail

SRC_TREE="$(dirname "$0")"
Expand All @@ -15,6 +16,13 @@ cargo build -p spacetimedb-standalone
export STDB_PATH="${STDB_PATH:-$(mktemp -d)}"
mkdir -p "$STDB_PATH/logs"

function cleanup {
echo "Removing ${STDB_PATH}"
rm -rf "$STDB_PATH"
}

trap cleanup EXIT

cp crates/standalone/log.conf "$STDB_PATH/log.conf"
# -i differs between GNU and BSD sed, so use a temp file
sed 's/spacetimedb=debug/spacetimedb=trace/g' "$STDB_PATH/log.conf" > "$STDB_PATH/log.conf.tmp" && \
Expand Down

0 comments on commit 68b9536

Please sign in to comment.