Skip to content
This repository has been archived by the owner on Sep 21, 2024. It is now read-only.

feat: Introduce "--storage-memory-cache-limit" #671

Merged
merged 2 commits into from
Oct 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@
"test-kubo",
"helpers"
]
}
}
1 change: 1 addition & 0 deletions images/orb/start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ orb sphere config set counterpart $COUNTERPART

ARGS="-i 0.0.0.0"
ARGS="${ARGS} --ipfs-api ${IPFS_API}"
ARGS="${ARGS} --storage-memory-cache-limit 50000000" # ~50MB storage memory cache limit

if ! [ -z "$NS_API" ]; then
ARGS="${ARGS} --name-resolver-api ${NS_API}"
Expand Down
5 changes: 5 additions & 0 deletions rust/noosphere-cli/src/native/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ pub enum OrbCommand {
/// The port that the gateway should listen on
#[clap(short, long, default_value = "4433")]
port: u16,

/// If set, the amount of memory that the storage provider may use
/// for caching in bytes.
#[clap(long)]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we get a short arg for this? e.g., short = 'S' or something

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Punting on this for now, as this is a low-level operator command

storage_memory_cache_limit: Option<usize>,
},
}

Expand Down
10 changes: 3 additions & 7 deletions rust/noosphere-cli/src/native/commands/serve.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,20 @@
//! Concrete implementations of subcommands related to running a Noosphere
//! gateway server

use crate::native::workspace::Workspace;
use anyhow::Result;

use noosphere_gateway::{start_gateway, GatewayScope};
use std::net::{IpAddr, TcpListener};

use url::Url;

use crate::native::workspace::Workspace;

use noosphere_gateway::{start_gateway, GatewayScope};

/// Start a Noosphere gateway server
pub async fn serve(
interface: IpAddr,
port: u16,
ipfs_api: Url,
name_resolver_api: Url,
cors_origin: Option<Url>,
workspace: &Workspace,
workspace: &mut Workspace,
) -> Result<()> {
workspace.ensure_sphere_initialized()?;

Expand Down
4 changes: 2 additions & 2 deletions rust/noosphere-cli/src/native/commands/sphere/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ use url::Url;
pub async fn sphere_create(owner_key: &str, workspace: &mut Workspace) -> Result<(Did, Mnemonic)> {
workspace.ensure_sphere_uninitialized()?;

let sphere_paths = SpherePaths::intialize(workspace.working_directory()).await?;
let sphere_paths = SpherePaths::initialize(workspace.working_directory()).await?;
jsantell marked this conversation as resolved.
Show resolved Hide resolved

let sphere_context_artifacts = SphereContextBuilder::default()
.create_sphere()
Expand Down Expand Up @@ -124,7 +124,7 @@ Type or paste the code here and press enter:"#
let cid = Cid::from_str(cid_string.trim())
.map_err(|_| anyhow!("Could not parse the authorization identity as a CID"))?;

let sphere_paths = SpherePaths::intialize(workspace.working_directory()).await?;
let sphere_paths = SpherePaths::initialize(workspace.working_directory()).await?;

{
let mut sphere_context = Arc::new(Mutex::new(
Expand Down
19 changes: 9 additions & 10 deletions rust/noosphere-cli/src/native/helpers/cli.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
use crate::{cli::Cli, invoke_cli, CliContext};
use anyhow::Result;
use clap::Parser;
use std::path::{Path, PathBuf};
use std::sync::Arc;
use std::sync::Mutex;
use tempfile::TempDir;
use tracing::{field, Level, Subscriber};
use tracing_subscriber::{prelude::*, Layer};

use crate::{cli::Cli, invoke_cli, workspace::Workspace};
use clap::Parser;

#[derive(Default)]
struct InfoCaptureVisitor {
message: String,
Expand Down Expand Up @@ -161,22 +160,22 @@ impl CliSimulator {
) -> Result<Option<Vec<String>>> {
let cli = self.parse_orb_command(command)?;

let workspace = Workspace::new(
&self.current_working_directory,
Some(self.noosphere_directory.path()),
)?;

debug!(
"In {}: orb {}",
self.current_working_directory.display(),
command.join(" ")
);

let context = CliContext {
cwd: self.current_working_directory.clone(),
global_config_directory: Some(self.noosphere_directory.path()),
};
let future = invoke_cli(cli, &context);
if capture_output {
let info = run_and_capture_info(invoke_cli(cli, workspace))?;
let info = run_and_capture_info(future)?;
Ok(Some(info))
} else {
invoke_cli(cli, workspace).await?;
future.await?;
Ok(None)
}
}
Expand Down
9 changes: 5 additions & 4 deletions rust/noosphere-cli/src/native/helpers/workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use crate::{
};
use noosphere::{
NoosphereContext, NoosphereContextConfiguration, NoosphereNetwork, NoosphereSecurity,
NoosphereStorage,
NoosphereStorage, NoosphereStorageConfig, NoosphereStoragePath,
};
use noosphere_core::{
context::HasSphereContext,
Expand All @@ -37,7 +37,7 @@ pub fn temporary_workspace() -> Result<(Workspace, (TempDir, TempDir))> {
let global_root = TempDir::new()?;

Ok((
Workspace::new(root.path(), Some(global_root.path()))?,
Workspace::new(root.path(), Some(global_root.path()), None)?,
(root, global_root),
))
}
Expand Down Expand Up @@ -156,8 +156,9 @@ impl SphereData {
/// state of this [SphereData]
pub async fn as_noosphere_context(&self) -> Result<NoosphereContext> {
NoosphereContext::new(NoosphereContextConfiguration {
storage: NoosphereStorage::Unscoped {
path: self.sphere_root().to_owned(),
storage: NoosphereStorage {
path: NoosphereStoragePath::Unscoped(self.sphere_root().to_owned()),
config: NoosphereStorageConfig::default(),
},
security: NoosphereSecurity::Insecure {
path: self.global_root().to_owned(),
Expand Down
68 changes: 51 additions & 17 deletions rust/noosphere-cli/src/native/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,7 @@ pub mod workspace;
#[cfg(any(test, feature = "helpers"))]
pub mod helpers;

use anyhow::Result;

use noosphere_core::tracing::initialize_tracing;

use clap::Parser;
use std::path::{Path, PathBuf};

use self::{
cli::{AuthCommand, Cli, ConfigCommand, FollowCommand, KeyCommand, OrbCommand, SphereCommand},
Expand All @@ -29,24 +25,61 @@ use self::{
},
workspace::Workspace,
};
use anyhow::Result;
use clap::Parser;
use noosphere_core::tracing::initialize_tracing;
use noosphere_storage::StorageConfig;

/// Additional context used to invoke a [Cli] command.
pub struct CliContext<'a> {
/// Path to the current working directory.
cwd: PathBuf,
/// Path to the global configuration directory, if provided.
global_config_directory: Option<&'a Path>,
}

#[cfg(not(doc))]
#[allow(missing_docs)]
pub async fn main() -> Result<()> {
initialize_tracing(None);
let context = CliContext {
cwd: std::env::current_dir()?,
global_config_directory: None,
};
invoke_cli(Cli::parse(), &context).await
}

let workspace = Workspace::new(&std::env::current_dir()?, None)?;
/// Invoke the CLI implementation imperatively.
///
/// This is the entrypoint used by orb when handling a command line invocation.
/// The [Cli] is produced by parsing the command line arguments, and internally
/// creates a new [Workspace] from the current working directory.
///
/// Use [invoke_cli_with_workspace] if using your own [Workspace].
pub async fn invoke_cli<'a>(cli: Cli, context: &CliContext<'a>) -> Result<()> {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

invoke_cli now creates a Workspace from its args rather than accept one so that we can always have the correct storage configuration on instantiation (this is the bulk of the follow up changes)

let storage_config = if let OrbCommand::Serve {
storage_memory_cache_limit,
..
} = &cli.command
{
Some(StorageConfig {
memory_cache_limit: *storage_memory_cache_limit,
})
} else {
None
};
let workspace = Workspace::new(
&context.cwd,
context.global_config_directory,
storage_config,
)?;

invoke_cli(Cli::parse(), workspace).await
invoke_cli_with_workspace(cli, workspace).await
}

/// Invoke the CLI implementation imperatively. This is the entrypoint used by
/// orb when handling a command line invocation. The [Cli] is produced by
/// parsing the command line arguments, and the [Workspace] is initialized from
/// the current working directory. The effect of invoking the CLI this way will
/// depend on the [Cli] and [Workspace] provided (results may vary significantly
/// depending on those inputs).
pub async fn invoke_cli(cli: Cli, mut workspace: Workspace) -> Result<()> {
/// Same as [invoke_cli], but enables the caller to provide their own
/// initialized [Workspace]
pub async fn invoke_cli_with_workspace(cli: Cli, mut workspace: Workspace) -> Result<()> {
match cli.command {
OrbCommand::Key { command } => match command {
KeyCommand::Create { name } => key_create(&name, &workspace).await?,
Expand Down Expand Up @@ -117,18 +150,19 @@ pub async fn invoke_cli(cli: Cli, mut workspace: Workspace) -> Result<()> {
name_resolver_api,
interface,
port,
..
} => {
serve(
interface,
port,
ipfs_api,
name_resolver_api,
cors_origin,
&workspace,
&mut workspace,
)
.await?
.await?;
}
};
}

Ok(())
}
2 changes: 1 addition & 1 deletion rust/noosphere-cli/src/native/paths.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ impl SpherePaths {
/// Initialize [SpherePaths] for a given root path. This has the effect of
/// creating the "private" directory hierarchy (starting from
/// [SPHERE_DIRECTORY] inside the root).
pub async fn intialize(root: &Path) -> Result<Self> {
pub async fn initialize(root: &Path) -> Result<Self> {
if !root.is_absolute() {
return Err(anyhow!(
"Must use an absolute path to initialize sphere directories; got {:?}",
Expand Down
28 changes: 18 additions & 10 deletions rust/noosphere-cli/src/native/workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use noosphere_core::context::{
SphereContentRead, SphereContext, SphereCursor, COUNTERPART, GATEWAY_URL,
};
use noosphere_core::data::{Did, Link, LinkRecord, MemoIpld};
use noosphere_storage::{KeyValueStore, SphereDb};
use noosphere_storage::{KeyValueStore, SphereDb, StorageConfig};
use serde_json::Value;
use std::path::{Path, PathBuf};
use std::sync::Arc;
Expand Down Expand Up @@ -39,6 +39,7 @@ pub struct Workspace {
key_storage: InsecureKeyStorage,
sphere_context: OnceCell<Arc<Mutex<CliSphereContext>>>,
working_directory: PathBuf,
storage_config: Option<StorageConfig>,
}

impl Workspace {
Expand All @@ -53,15 +54,17 @@ impl Workspace {
Ok(self
.sphere_context
.get_or_try_init(|| async {
Ok(Arc::new(Mutex::new(
SphereContextBuilder::default()
.open_sphere(None)
.at_storage_path(self.require_sphere_paths()?.root())
.reading_keys_from(self.key_storage.clone())
.build()
.await?
.into(),
))) as Result<Arc<Mutex<CliSphereContext>>, anyhow::Error>
let mut builder = SphereContextBuilder::default()
.open_sphere(None)
.at_storage_path(self.require_sphere_paths()?.root())
.reading_keys_from(self.key_storage.clone());

if let Some(storage_config) = self.storage_config.as_ref() {
builder = builder.with_storage_config(storage_config);
}

Ok(Arc::new(Mutex::new(builder.build().await?.into())))
as Result<Arc<Mutex<CliSphereContext>>, anyhow::Error>
})
.await?
.clone())
Expand Down Expand Up @@ -312,9 +315,13 @@ impl Workspace {
/// - Windows: C:\Users\<user>\AppData\Roaming\subconscious\noosphere\config
///
/// On Linux, an $XDG_CONFIG_HOME environment variable will be respected if set.
///
/// Additionally, a [StorageConfig] may be provided to configure the storage used
/// by the opened sphere.
pub fn new(
working_directory: &Path,
custom_noosphere_directory: Option<&Path>,
storage_config: Option<StorageConfig>,
) -> Result<Self> {
let sphere_paths = SpherePaths::discover(Some(working_directory)).map(Arc::new);

Expand All @@ -340,6 +347,7 @@ impl Workspace {
key_storage,
sphere_context: OnceCell::new(),
working_directory: working_directory.to_owned(),
storage_config,
};

Ok(workspace)
Expand Down
6 changes: 2 additions & 4 deletions rust/noosphere-storage/examples/bench/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,17 +132,15 @@ impl BenchmarkStorage {
))]
let (storage, storage_name) = {
(
noosphere_storage::SledStorage::new(noosphere_storage::SledStorageInit::Path(
storage_path.into(),
))?,
noosphere_storage::SledStorage::new(&storage_path)?,
"SledDbStorage",
)
};

#[cfg(all(not(target_arch = "wasm32"), feature = "rocksdb"))]
let (storage, storage_name) = {
(
noosphere_storage::RocksDbStorage::new(storage_path.into())?,
noosphere_storage::RocksDbStorage::new(&storage_path)?,
"RocksDbStorage",
)
};
Expand Down
25 changes: 25 additions & 0 deletions rust/noosphere-storage/src/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
use crate::storage::Storage;
use anyhow::Result;
use async_trait::async_trait;
use noosphere_common::ConditionalSend;
use std::path::Path;

/// Generalized configurations for [ConfigurableStorage].
#[derive(Debug, Clone, Default)]
pub struct StorageConfig {
/// If set, the size limit in bytes of a memory-based cache.
pub memory_cache_limit: Option<usize>,
}

/// [Storage] that can be customized via [StorageConfig].
///
/// Configurations are generalized across storage providers,
/// and may have differing underlying semantics.
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
pub trait ConfigurableStorage: Storage {
async fn open_with_config<P: AsRef<Path> + ConditionalSend>(
path: P,
config: StorageConfig,
) -> Result<Self>;
}
4 changes: 2 additions & 2 deletions rust/noosphere-storage/src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::Storage;
use anyhow::Result;

#[cfg(not(target_arch = "wasm32"))]
use crate::{SledStorage, SledStorageInit, SledStore};
use crate::{SledStorage, SledStore};

#[cfg(not(target_arch = "wasm32"))]
pub async fn make_disposable_store() -> Result<SledStore> {
Expand All @@ -13,7 +13,7 @@ pub async fn make_disposable_store() -> Result<SledStore> {
.into_iter()
.map(String::from)
.collect();
let provider = SledStorage::new(SledStorageInit::Path(temp_dir.join(temp_name)))?;
let provider = SledStorage::new(temp_dir.join(temp_name))?;
provider.get_block_store("foo").await
}

Expand Down
Loading