Skip to content

Commit

Permalink
Isolate task triggers from global object
Browse files Browse the repository at this point in the history
  • Loading branch information
max-lt committed Feb 26, 2024
1 parent 311a4d3 commit 7ab7512
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 50 deletions.
3 changes: 1 addition & 2 deletions examples/serve-new.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,8 @@ async fn handle_request(data: Data<AppState>, req: HttpRequest) -> HttpResponse
}
};

debug!("handle_request done t={}", start.elapsed().as_millis());
debug!("handle_request done in {}ms", start.elapsed().as_millis());

debug!("waiting for js worker to finish t={}", start.elapsed().as_millis());
handle.join().unwrap();

response
Expand Down
2 changes: 1 addition & 1 deletion examples/serve-same.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ async fn handle_request(data: Data<AppState>, req: HttpRequest) -> HttpResponse
}
};

debug!("handle_request done {}", start.elapsed().as_millis());
debug!("handle_request done in {}ms", start.elapsed().as_millis());

response
}
Expand Down
8 changes: 6 additions & 2 deletions src/ext/runtime.js
Original file line number Diff line number Diff line change
Expand Up @@ -297,8 +297,6 @@ import * as eventSource from "ext:deno_fetch/27_eventsource.js";
EventSource: nonEnumerable(eventSource.EventSource),

// Events
triggerScheduledEvent: nonEnumerable(scheduledEvent.triggerScheduledEvent),
triggerFetchEvent: nonEnumerable(fetchEvent.triggerFetchEvent),
addEventListener: nonEnumerable(addEventListener),

// Branding as a WebIDL object
Expand Down Expand Up @@ -415,5 +413,11 @@ import * as eventSource from "ext:deno_fetch/27_eventsource.js";
core.setReportExceptionCallback(event.reportException);

// core.setWasmStreamingCallback(fetch.handleWasmStreaming);

// Return event trigger functions to be used by the host
return {
scheduled: scheduledEvent.triggerScheduledEvent,
fetch: fetchEvent.triggerFetchEvent,
};
};
}
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ mod runtime;
mod task;
pub mod snapshot;

pub (crate) mod util;

pub (crate) use runtime::extensions;

pub use runtime::Worker;
Expand Down
41 changes: 31 additions & 10 deletions src/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use deno_core::error::AnyError;
use deno_core::JsRuntime;

use deno_core::url::Url;
use deno_core::v8;
use deno_core::Snapshot;

use log::debug;
Expand Down Expand Up @@ -71,7 +72,9 @@ pub(crate) fn extensions(for_snapshot: bool) -> Vec<deno_core::Extension> {
}

pub struct Worker {
js_runtime: deno_core::JsRuntime,
pub(crate) js_runtime: deno_core::JsRuntime,
pub(crate) trigger_fetch: deno_core::v8::Global<deno_core::v8::Function>,
pub(crate) trigger_scheduled: deno_core::v8::Global<deno_core::v8::Function>,
}

impl Worker {
Expand Down Expand Up @@ -101,18 +104,33 @@ impl Worker {

debug!("runtime created, bootstrapping...");

let trigger_fetch;
let trigger_scheduled;

// Bootstrap
{
let script = format!("globalThis.bootstrap('{}')", USER_AGENT);
let script = deno_core::ModuleCodeString::from(script);

match js_runtime.execute_script(deno_core::located_script_name!(), script) {
Ok(triggers) => {
let scope = &mut js_runtime.handle_scope();

let triggers = v8::Local::new(scope, triggers);

match js_runtime.execute_script(
deno_core::located_script_name!(),
deno_core::ModuleCodeString::from(script),
) {
Ok(_) => debug!("bootstrap succeeded"),
debug!("bootstrap succeeded with triggers: {:?}", triggers);

let object: v8::Local<v8::Object> = match triggers.try_into() {
Ok(object) => object,
Err(err) => panic!("failed to convert triggers to object: {:?}", err),
};

trigger_fetch = crate::util::extract_trigger("fetch", scope, object).expect("fetch trigger not found");
trigger_scheduled = crate::util::extract_trigger("scheduled", scope, object).expect("scheduled trigger not found");
}
Err(err) => panic!("bootstrap failed: {:?}", err),
}
}
};

debug!("runtime bootstrapped, evaluating main module...");

Expand All @@ -134,14 +152,17 @@ impl Worker {

debug!("main module evaluated");

Ok(Self { js_runtime })
Ok(Self {
js_runtime,
trigger_fetch,
trigger_scheduled,
})
}

pub async fn exec(&mut self, mut task: Task) -> Result<(), AnyError> {
debug!("executing task {:?}", task.task_type());

task.trigger(&mut self.js_runtime)
.expect("failed to trigger task")?;
crate::util::exec_task(self, &mut task);

let opts = deno_core::PollEventLoopOptions {
wait_for_inspector: false,
Expand Down
35 changes: 0 additions & 35 deletions src/task.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,3 @@
use deno_core::error::AnyError;
use deno_core::v8::Global;
use deno_core::v8::Value;
use deno_core::JsRuntime;
use deno_core::ModuleCodeString;
use deno_core::ResourceId;

use crate::FetchInit;
use crate::ScheduledInit;

Expand All @@ -26,32 +19,4 @@ impl Task {
Task::Scheduled(_) => TaskType::Scheduled,
}
}

fn init(&mut self, js_runtime: &mut JsRuntime) -> ResourceId {
let op_state_rc = js_runtime.op_state();
let mut op_state = op_state_rc.borrow_mut();

match self {
Task::Fetch(data) => op_state.resource_table.add(data.take().unwrap()),
Task::Scheduled(data) => op_state.resource_table.add(data.take().unwrap()),
}
}

pub fn trigger(
&mut self,
js_runtime: &mut JsRuntime,
) -> Option<Result<Global<Value>, AnyError>> {
let rid = self.init(js_runtime);

match self {
Task::Fetch(_) => Some(js_runtime.execute_script(
deno_core::located_script_name!(),
ModuleCodeString::from(format!("globalThis.triggerFetchEvent({rid})")),
)),
Task::Scheduled(_) => Some(js_runtime.execute_script(
deno_core::located_script_name!(),
ModuleCodeString::from(format!("globalThis.triggerScheduledEvent({rid})")),
)),
}
}
}
55 changes: 55 additions & 0 deletions src/util.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
use deno_core::v8;

use crate::Task;
use crate::Worker;

pub(crate) fn extract_trigger<'a>(
name: &str,
scope: &mut v8::HandleScope<'a>,
object: v8::Local<'a, v8::Object>,
) -> Option<v8::Global<v8::Function>> {
let key = v8::String::new(scope, name).unwrap().into();

let ret = match object.get(scope, key) {
Some(fetch) => fetch,
None => return None,
};

let ret: v8::Local<v8::Function> = match ret.try_into() {
Ok(ret) => ret,
Err(_) => return None,
};

Some(v8::Global::new(scope, ret))
}

pub(crate) fn exec_task(worker: &mut Worker, task: &mut Task) {
let rid = {
let op_state_rc = worker.js_runtime.op_state();
let mut op_state = op_state_rc.borrow_mut();

match task {
Task::Fetch(data) => op_state.resource_table.add(data.take().unwrap()),
Task::Scheduled(data) => op_state.resource_table.add(data.take().unwrap()),
}
};

let scope = &mut worker.js_runtime.handle_scope();

let trigger = v8::Local::new(
scope,
match task {
Task::Fetch(_) => &worker.trigger_fetch,
Task::Scheduled(_) => &worker.trigger_scheduled,
},
);

let recv = v8::undefined(scope);

let rid = v8::Integer::new(scope, rid as i32).into();

match trigger.call(scope, recv.into(), &[rid]) {
Some(_) => log::debug!("successfully called trigger"),
None => log::error!("failed to call trigger"),
};
}

0 comments on commit 7ab7512

Please sign in to comment.