Skip to content

Commit

Permalink
fix: polishing the worker bootstrap phase and ridding annoying cache …
Browse files Browse the repository at this point in the history
…adaptor errors emitted from `transformers.js` (#453)

* fix: november cleanup

* stamp(sb_ai): ignore `cache_adapter` errors when is `debug`

- not throwing Cache Adapter errors when is `debug`

(cherry picked from commit 1396d42)

---------

Co-authored-by: kallebysantos <[email protected]>
  • Loading branch information
nyannyacha and kallebysantos authored Nov 29, 2024
1 parent 954ab6d commit 18d8f69
Show file tree
Hide file tree
Showing 3 changed files with 186 additions and 106 deletions.
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

0 comments on commit 18d8f69

Please sign in to comment.