Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: polishing the worker bootstrap phase and ridding annoying cache adaptor errors emitted from transformers.js #453

Merged
merged 2 commits into from
Nov 29, 2024
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
163 changes: 103 additions & 60 deletions crates/base/src/deno_runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::utils::json;
use crate::utils::path::find_up;
use crate::utils::units::{bytes_to_display, mib_to_bytes, percentage_value};

use anyhow::{anyhow, bail, Error};
use anyhow::{anyhow, bail, Context, Error};
use arc_swap::ArcSwapOption;
use base_mem_check::{MemCheckState, WorkerHeapStatistics};
use base_rt::DenoRuntimeDropToken;
Expand All @@ -18,15 +18,16 @@ use deno_core::error::{AnyError, JsError};
use deno_core::url::Url;
use deno_core::v8::{self, GCCallbackFlags, GCType, HeapStatistics, Isolate};
use deno_core::{
located_script_name, serde_json, JsRuntime, ModuleCodeString, ModuleId, ModuleLoader,
ModuleSpecifier, OpState, PollEventLoopOptions, ResolutionKind, RuntimeOptions,
serde_json, JsRuntime, ModuleId, ModuleLoader, ModuleSpecifier, OpState, PollEventLoopOptions,
ResolutionKind, RuntimeOptions,
};
use deno_http::DefaultHttpPropertyExtractor;
use deno_tls::deno_native_certs::load_native_certs;
use deno_tls::rustls::RootCertStore;
use deno_tls::RootCertStoreProvider;
use futures_util::future::poll_fn;
use futures_util::task::AtomicWaker;
use futures_util::FutureExt;
use log::error;
use once_cell::sync::{Lazy, OnceCell};
use sb_core::http::sb_core_http;
Expand Down Expand Up @@ -205,15 +206,45 @@ impl MemCheck {
}

pub trait GetRuntimeContext {
fn get_runtime_context() -> impl Serialize;
}
fn get_runtime_context(
conf: &WorkerRuntimeOpts,
use_inspector: bool,
version: Option<&str>,
) -> impl Serialize {
serde_json::json!({
"target": env!("TARGET"),
"kind": conf.to_worker_kind().to_string(),
"debug": cfg!(debug_assertions),
"inspector": use_inspector,
"version": {
"runtime": version.unwrap_or("0.1.0"),
"deno": MAYBE_DENO_VERSION
.get()
.map(|it| &**it)
.unwrap_or("UNKNOWN"),
},
"flags": {
"SHOULD_DISABLE_DEPRECATED_API_WARNING": SHOULD_DISABLE_DEPRECATED_API_WARNING
.get()
.copied()
.unwrap_or_default(),
"SHOULD_USE_VERBOSE_DEPRECATED_API_WARNING": SHOULD_USE_VERBOSE_DEPRECATED_API_WARNING
.get()
.copied()
.unwrap_or_default()
}
})
}

impl GetRuntimeContext for () {
fn get_runtime_context() -> impl Serialize {
serde_json::json!(null)
fn get_extra_context() -> impl Serialize {
serde_json::json!({})
}
}

type DefaultRuntimeContext = ();

impl GetRuntimeContext for DefaultRuntimeContext {}

#[derive(Debug, Clone)]
struct GlobalMainContext(v8::Global<v8::Context>);

Expand All @@ -240,7 +271,7 @@ pub enum WillTerminateReason {
WallClock,
}

pub struct DenoRuntime<RuntimeContext = ()> {
pub struct DenoRuntime<RuntimeContext = DefaultRuntimeContext> {
pub js_runtime: ManuallyDrop<JsRuntime>,
pub drop_token: CancellationToken,
pub env_vars: HashMap<String, String>, // TODO: does this need to be pub?
Expand Down Expand Up @@ -282,7 +313,7 @@ impl<RuntimeContext> Drop for DenoRuntime<RuntimeContext> {
}
}

impl DenoRuntime<()> {
impl DenoRuntime<DefaultRuntimeContext> {
pub async fn acquire() -> OwnedSemaphorePermit {
RUNTIME_CREATION_SEM
.with(|v| v.clone())
Expand Down Expand Up @@ -668,10 +699,10 @@ where
let global_obj = context_local.global(scope);
let bootstrap_str =
v8::String::new_external_onebyte_static(scope, b"bootstrap").unwrap();
let bootstrap_ns: v8::Local<v8::Object> = global_obj
let bootstrap_ns = global_obj
.get(scope, bootstrap_str.into())
.unwrap()
.try_into()
.to_object(scope)
.unwrap();

let dispatch_load_event_fn_str =
Expand Down Expand Up @@ -717,56 +748,17 @@ where
op_state.put(dispatch_fns);
op_state.put(promise_metrics.clone());
op_state.put(GlobalMainContext(main_context));
}

{
let op_state_rc = js_runtime.op_state();
let mut op_state = op_state_rc.borrow_mut();

// NOTE(Andreespirela): We do this because "NODE_DEBUG" is trying to be read during
// initialization, But we need the gotham state to be up-to-date.
op_state.put(sb_env::EnvVars::default());
}

// Bootstrapping stage
let script = format!(
"globalThis.bootstrapSBEdge({}, {})",
serde_json::json!([
// 0: target
env!("TARGET"),
// 1: isUserWorker
conf.is_user_worker(),
// 2: isEventsWorker
conf.is_events_worker(),
// 3: edgeRuntimeVersion
option_env!("GIT_V_TAG").unwrap_or("0.1.0"),
// 4: denoVersion
MAYBE_DENO_VERSION
.get()
.map(|it| &**it)
.unwrap_or("UNKNOWN"),
// 5: shouldDisableDeprecatedApiWarning
SHOULD_DISABLE_DEPRECATED_API_WARNING
.get()
.copied()
.unwrap_or_default(),
// 6: shouldUseVerboseDeprecatedApiWarning
SHOULD_USE_VERBOSE_DEPRECATED_API_WARNING
.get()
.copied()
.unwrap_or_default(),
]),
{
let mut runtime_context = serde_json::json!(RuntimeContext::get_runtime_context());

json::merge_object(
&mut runtime_context,
&conf
.as_user_worker()
.and_then(|it| it.context.clone())
.map(serde_json::Value::Object)
.unwrap_or_else(|| serde_json::json!({})),
);

runtime_context
}
);

if let Some(inspector) = maybe_inspector.clone() {
inspector.server.register_inspector(
main_module_url.to_string(),
Expand All @@ -788,9 +780,60 @@ where
.put(MemCheckWaker::from(mem_check.waker.clone()));
}

// Bootstrapping stage
let (runtime_context, extra_context, bootstrap_fn) = {
let runtime_context = serde_json::json!(RuntimeContext::get_runtime_context(
&conf,
has_inspector,
option_env!("GIT_V_TAG"),
));

let extra_context = {
let mut context = serde_json::json!(RuntimeContext::get_extra_context());

json::merge_object(
&mut context,
&conf
.as_user_worker()
.and_then(|it| it.context.clone())
.map(serde_json::Value::Object)
.unwrap_or_else(|| serde_json::json!({})),
);

context
};

let context = js_runtime.main_context();
let scope = &mut js_runtime.handle_scope();
let context_local = v8::Local::new(scope, context);
let global_obj = context_local.global(scope);
let bootstrap_str =
v8::String::new_external_onebyte_static(scope, b"bootstrapSBEdge").unwrap();
let bootstrap_fn = v8::Local::<v8::Function>::try_from(
global_obj.get(scope, bootstrap_str.into()).unwrap(),
)
.unwrap();

let runtime_context_local = deno_core::serde_v8::to_v8(scope, runtime_context)
.context("failed to convert to v8 value")?;
let runtime_context_global = v8::Global::new(scope, runtime_context_local);
let extra_context_local = deno_core::serde_v8::to_v8(scope, extra_context)
.context("failed to convert to v8 value")?;
let extra_context_global = v8::Global::new(scope, extra_context_local);
let bootstrap_fn_global = v8::Global::new(scope, bootstrap_fn);

(
runtime_context_global,
extra_context_global,
bootstrap_fn_global,
)
};

js_runtime
.execute_script(located_script_name!(), ModuleCodeString::from(script))
.expect("Failed to execute bootstrap script");
.call_with_args(&bootstrap_fn, &[runtime_context, extra_context])
.now_or_never()
.transpose()
.context("failed to execute bootstrap script")?;

{
// run inside a closure, so op_state_rc is released
Expand Down Expand Up @@ -1813,7 +1856,7 @@ mod test {
struct WithSyncFileAPI;

impl GetRuntimeContext for WithSyncFileAPI {
fn get_runtime_context() -> impl Serialize {
fn get_extra_context() -> impl Serialize {
serde_json::json!({
"useReadSyncFileAPI": true,
})
Expand Down Expand Up @@ -2559,7 +2602,7 @@ mod test {
struct Ctx;

impl GetRuntimeContext for Ctx {
fn get_runtime_context() -> impl Serialize {
fn get_extra_context() -> impl Serialize {
serde_json::json!({
"useReadSyncFileAPI": true,
"shouldBootstrapMockFnThrowError": true,
Expand Down
9 changes: 7 additions & 2 deletions crates/sb_ai/js/onnxruntime/cache_adapter.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { primordials } from 'ext:core/mod.js';
import { primordials, internals } from 'ext:core/mod.js';
import * as webidl from 'ext:deno_webidl/00_webidl.js';
import * as DenoCaches from 'ext:deno_cache/01_cache.js';

Expand All @@ -9,7 +9,7 @@ const {

async function open(cacheName, _next) {
if (!ALLOWED_CACHE_NAMES.includes(cacheName)) {
throw new Error("Web Cache is not available in this context");
return await notAvailable();
}

// NOTE(kallebysantos): Since default `Web Cache` is not alloed we need to manually create a new
Expand Down Expand Up @@ -56,6 +56,11 @@ CacheStoragePrototype.open = async function (args) {
// scenario where `Web Cache` is free to use, the `sb_ai: Cache Adapter` should act as request
// middleware ie. add new behaviour on top of `next()`
async function notAvailable() {
// Ignore errors when `debug = true`
if(internals,internals.bootstrapArgs.opts.debug) {
return;
}

throw new Error("Web Cache is not available in this context");
}

Expand Down
Loading