Skip to content

Commit

Permalink
Merge pull request wasmerio#343 from wasmerio/global-runtime
Browse files Browse the repository at this point in the history
Use a global `Runtime` when one isn't explicitly provided
  • Loading branch information
Michael Bryan authored Nov 27, 2023
2 parents abf66f2 + 3592405 commit e55dfe7
Show file tree
Hide file tree
Showing 10 changed files with 236 additions and 55 deletions.
6 changes: 3 additions & 3 deletions package-lock.json

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

4 changes: 2 additions & 2 deletions src/container.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use shared_buffer::OwnedBuffer;
use wasm_bindgen::{prelude::wasm_bindgen, JsCast};
use wasmer_wasix::{runtime::resolver::PackageSpecifier, Runtime as _};

use crate::{utils::Error, Runtime};
use crate::{utils::Error, JsRuntime};

#[wasm_bindgen]
pub struct Container {
Expand All @@ -28,7 +28,7 @@ impl Container {
/// Download a package from the registry.
pub async fn from_registry(
package_specifier: &str,
runtime: &Runtime,
runtime: &JsRuntime,
) -> Result<Container, Error> {
let source = runtime.source();
let package_specifier: PackageSpecifier = package_specifier
Expand Down
25 changes: 13 additions & 12 deletions src/facade.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@ use web_sys::{ReadableStream, WritableStream};
use crate::{
instance::ExitCondition,
utils::{Error, GlobalScope},
Instance, Runtime, SpawnOptions,
Instance, JsRuntime, Runtime, SpawnOptions,
};

/// The entrypoint to the Wasmer SDK.
#[wasm_bindgen]
pub struct Wasmer {
runtime: Runtime,
runtime: Arc<Runtime>,
_api_key: Option<String>,
}

Expand All @@ -35,17 +35,17 @@ impl Wasmer {
pub fn new(cfg: Option<WasmerConfig>) -> Result<Wasmer, Error> {
let cfg = cfg.unwrap_or_default();

let mut runtime = Runtime::with_pool_size(cfg.pool_size())?;
let mut runtime = Runtime::with_defaults()?;

if let Some(registry_url) = cfg.parse_registry_url() {
runtime.set_registry(&registry_url)?;
runtime.set_registry(&registry_url, None)?;
}
if let Some(gateway) = cfg.network_gateway() {
runtime.set_network_gateway(gateway.into());
}

Ok(Wasmer {
runtime,
runtime: Arc::new(runtime),
_api_key: cfg.api_key().map(String::from),
})
}
Expand All @@ -59,8 +59,8 @@ impl Wasmer {
self.spawn(app_id, config).await
}

pub fn runtime(&self) -> Runtime {
self.runtime.clone()
pub fn runtime(&self) -> JsRuntime {
JsRuntime::from(self.runtime.clone())
}
}

Expand All @@ -70,17 +70,18 @@ impl Wasmer {
let specifier: PackageSpecifier = app_id.parse()?;
let config = config.unwrap_or_default();

let pkg = BinaryPackage::from_registry(&specifier, &self.runtime).await?;
let runtime = match config.runtime().as_runtime() {
Some(rt) => Arc::clone(&*rt),
None => Arc::clone(&self.runtime),
};

let pkg = BinaryPackage::from_registry(&specifier, &*runtime).await?;
let command_name = config
.command()
.as_string()
.or_else(|| pkg.entrypoint_cmd.clone())
.context("No command name specified")?;

let runtime = match config.runtime().as_runtime() {
Some(rt) => Arc::new(rt),
None => Arc::new(self.runtime.clone()),
};
let tasks = Arc::clone(runtime.task_manager());

let mut runner = WasiRunner::new();
Expand Down
146 changes: 146 additions & 0 deletions src/js_runtime.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
use std::{
num::NonZeroUsize,
ops::{Deref, DerefMut},
sync::Arc,
};

use wasm_bindgen::{prelude::wasm_bindgen, JsCast};

use crate::{runtime::Runtime, tasks::ThreadPool, utils::Error};

#[derive(Clone, Debug, wasm_bindgen_derive::TryFromJsValue)]
#[wasm_bindgen(js_name = "Runtime")]
pub struct JsRuntime {
// Note: This is just a wrapper around the "real" runtime implementation.
// We need it because most JS-facing methods will want to accept/return an
// `Arc<Runtime>`, but wasm-bindgen doesn't support passing Arc around
// directly.
rt: Arc<Runtime>,
}

#[wasm_bindgen(js_class = "Runtime")]
impl JsRuntime {
#[wasm_bindgen(constructor)]
pub fn new(options: Option<RuntimeOptions>) -> Result<JsRuntime, Error> {
let pool_size = options.as_ref().and_then(|options| options.pool_size());

let pool = match pool_size {
Some(size) => {
let size = NonZeroUsize::new(size).unwrap_or(NonZeroUsize::MIN);
ThreadPool::new(size)
}
None => ThreadPool::new_with_max_threads()?,
};

let registry = match options.as_ref().and_then(|opts| opts.registry()) {
Some(registry_url) => registry_url.resolve(),
None => Some(crate::DEFAULT_REGISTRY.to_string()),
};

let mut rt = Runtime::new(pool);

if let Some(registry) = registry.as_deref() {
let api_key = options.as_ref().and_then(|opts| opts.api_key());
rt.set_registry(registry, api_key.as_deref())?;
}

Ok(JsRuntime { rt: Arc::new(rt) })
}

/// Get a reference to the global runtime, optionally initializing it if
/// requested.
pub fn global(initialize: Option<bool>) -> Result<Option<JsRuntime>, Error> {
match Runtime::global() {
Some(rt) => Ok(Some(JsRuntime { rt })),
None if initialize == Some(true) => {
let rt = Runtime::lazily_initialized()?;
Ok(Some(JsRuntime { rt }))
}
None => Ok(None),
}
}
}

impl Deref for JsRuntime {
type Target = Arc<Runtime>;

fn deref(&self) -> &Self::Target {
&self.rt
}
}

impl DerefMut for JsRuntime {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.rt
}
}

impl From<Arc<Runtime>> for JsRuntime {
fn from(value: Arc<Runtime>) -> Self {
JsRuntime { rt: value }
}
}

impl AsRef<Arc<Runtime>> for JsRuntime {
fn as_ref(&self) -> &Arc<Runtime> {
self
}
}

#[wasm_bindgen(typescript_custom_section)]
const RUNTIME_OPTIONS_TYPE_DECLARATION: &str = r#"
/**
* Options used when constructing a {@link Runtime}.
*/
export type RuntimeOptions = {
/**
* The number of worker threads to use.
*/
poolSize?: number;
/**
* The GraphQL endpoint for the Wasmer registry used when looking up
* packages.
*
* Defaults to `"https://registry.wasmer.io/graphql"`.
*
* If `null`, no queries will be made to the registry.
*/
registry?: string | null;
/**
* An optional API key to use when sending requests to the Wasmer registry.
*/
apiKey?: string;
};
"#;

#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(typescript_type = "RuntimeOptions")]
pub type RuntimeOptions;

#[wasm_bindgen(method, getter, js_name = "poolSize")]
fn pool_size(this: &RuntimeOptions) -> Option<usize>;

#[wasm_bindgen(method, getter)]
fn registry(this: &RuntimeOptions) -> Option<MaybeRegistryUrl>;

#[wasm_bindgen(method, getter, js_name = "apiKey")]
fn api_key(this: &RuntimeOptions) -> Option<String>;

#[wasm_bindgen(typescript_type = "string | null | undefined")]
type MaybeRegistryUrl;
}

impl MaybeRegistryUrl {
fn resolve(&self) -> Option<String> {
if self.is_undefined() {
Some(crate::DEFAULT_REGISTRY.to_string())
} else if self.is_null() {
None
} else if let Some(s) = self.dyn_ref::<js_sys::JsString>() {
Some(s.into())
} else {
unreachable!()
}
}
}
6 changes: 5 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ mod container;
mod facade;
pub mod fs;
mod instance;
mod js_runtime;
mod logging;
mod net;
mod options;
Expand All @@ -20,15 +21,16 @@ mod ws;

use std::sync::Mutex;

pub(crate) use crate::runtime::Runtime;
pub use crate::{
container::{Container, Manifest, Volume},
facade::{Wasmer, WasmerConfig},
fs::{Directory, DirectoryInit},
instance::{Instance, JsOutput},
js_runtime::{JsRuntime, RuntimeOptions},
logging::initialize_logger,
options::{RunOptions, SpawnOptions},
run::run,
runtime::Runtime,
utils::StringOrBytes,
};

Expand All @@ -38,6 +40,8 @@ use wasm_bindgen::prelude::wasm_bindgen;
pub(crate) const USER_AGENT: &str = concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION"));
pub(crate) const DEFAULT_RUST_LOG: &[&str] = &["warn"];
pub(crate) static CUSTOM_WORKER_URL: Lazy<Mutex<Option<String>>> = Lazy::new(Mutex::default);
pub(crate) const DEFAULT_REGISTRY: &str =
wasmer_wasix::runtime::resolver::WapmSource::WASMER_PROD_ENDPOINT;

#[wasm_bindgen]
pub fn wat2wasm(wat: String) -> Result<js_sys::Uint8Array, utils::Error> {
Expand Down
7 changes: 1 addition & 6 deletions src/logging.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,12 +105,7 @@ impl Write for ConsoleLogger {
impl Drop for ConsoleLogger {
fn drop(&mut self) {
if !self.buffer.is_empty() {
if let Err(e) = self.flush() {
tracing::warn!(
error = &e as &dyn std::error::Error,
"An error occurred while flushing",
);
}
let _ = self.flush();
}
}
}
6 changes: 3 additions & 3 deletions src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use virtual_fs::TmpFileSystem;
use wasm_bindgen::{prelude::wasm_bindgen, JsCast, JsValue, UnwrapThrowExt};
use wasmer_wasix::WasiEnvBuilder;

use crate::{utils::Error, Directory, DirectoryInit, Runtime, StringOrBytes};
use crate::{utils::Error, Directory, DirectoryInit, JsRuntime, StringOrBytes};

#[wasm_bindgen]
extern "C" {
Expand Down Expand Up @@ -229,13 +229,13 @@ impl RunOptions {
}

impl OptionalRuntime {
pub(crate) fn as_runtime(&self) -> Option<Runtime> {
pub(crate) fn as_runtime(&self) -> Option<JsRuntime> {
let js_value: &JsValue = self.as_ref();

if js_value.is_undefined() {
None
} else {
let rt = Runtime::try_from(js_value).expect_throw("Expected a runtime");
let rt = JsRuntime::try_from(js_value).expect_throw("Expected a runtime");
Some(rt)
}
}
Expand Down
5 changes: 2 additions & 3 deletions src/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ pub async fn run(wasm_module: WasmModule, config: RunOptions) -> Result<Instance
let _span = tracing::debug_span!("run").entered();

let runtime = match config.runtime().as_runtime() {
Some(rt) => Arc::new(rt.clone()),
None => Arc::new(Runtime::with_pool_size(None)?),
Some(rt) => Arc::clone(&*rt),
None => Runtime::lazily_initialized()?,
};

let program_name = config
Expand All @@ -38,7 +38,6 @@ pub async fn run(wasm_module: WasmModule, config: RunOptions) -> Result<Instance
Box::new(move |module| {
let _span = tracing::debug_span!("run").entered();
let result = builder.run(module).map_err(anyhow::Error::new);
tracing::warn!(?result);
let _ = exit_code_tx.send(ExitCondition::from_result(result));
}),
)?;
Expand Down
Loading

0 comments on commit e55dfe7

Please sign in to comment.