-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
15 changed files
with
461 additions
and
316 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
# OpenWorkers runtime | ||
|
||
OpenWorkers is a runtime for running javascript code in a serverless environment. | ||
It is designed to be used with the [OpenWorkers CLI](https://github.com/openworkers/openworkers-cli). | ||
|
||
This repository contains the runtime library. | ||
|
||
## Usage | ||
|
||
### Build all examples | ||
```bash | ||
cargo build --release --examples | ||
``` | ||
|
||
### Snapshot the runtime | ||
```bash | ||
cargo run --example snapshot | ||
``` | ||
|
||
### Run the demo server | ||
#### With a new runtime instance for each request | ||
```bash | ||
cargo run --example serve-new -- examples/serve.js | ||
``` | ||
|
||
#### With the same runtime instance for each request | ||
```bash | ||
cargo run --example serve-same -- examples/serve.js | ||
``` | ||
|
||
### Execute a scheduled task | ||
```bash | ||
export RUST_LOG=openworkers_runtime=debug,serve=debug # Optional | ||
|
||
cargo run --example scheduled -- examples/scheduled.js | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
use bytes::Bytes; | ||
|
||
use log::debug; | ||
use log::error; | ||
use openworkers_runtime::FetchInit; | ||
use openworkers_runtime::Task; | ||
use openworkers_runtime::Url; | ||
use openworkers_runtime::Worker; | ||
|
||
use tokio::sync::oneshot::channel; | ||
|
||
use actix_web::{App, HttpServer}; | ||
|
||
use actix_web::web; | ||
use actix_web::web::Data; | ||
use actix_web::HttpRequest; | ||
use actix_web::HttpResponse; | ||
|
||
struct AppState { | ||
url: Url, | ||
} | ||
|
||
async fn handle_request(data: Data<AppState>, req: HttpRequest) -> HttpResponse { | ||
debug!( | ||
"handle_request of {}: {} {} in thread {:?}", | ||
data.url.path().split('/').last().unwrap(), | ||
req.method(), | ||
req.uri(), | ||
std::thread::current().id() | ||
); | ||
|
||
let url = data.url.clone(); | ||
let start = tokio::time::Instant::now(); | ||
|
||
let req = http_v02::Request::builder() | ||
.uri(req.uri()) | ||
.body(Default::default()) | ||
.unwrap(); | ||
|
||
let url_clone = url.clone(); | ||
|
||
let (res_tx, res_rx) = channel::<http_v02::Response<Bytes>>(); | ||
let task = Task::Fetch(Some(FetchInit::new(req, res_tx))); | ||
|
||
let handle = std::thread::spawn(move || { | ||
let local = tokio::task::LocalSet::new(); | ||
|
||
let tasks = local.spawn_local(async move { | ||
debug!("create worker"); | ||
let mut worker = Worker::new(url_clone).await.unwrap(); | ||
|
||
debug!("exec fetch task"); | ||
match worker.exec(task).await { | ||
Ok(()) => debug!("exec completed"), | ||
Err(err) => error!("exec did not complete: {err}"), | ||
} | ||
}); | ||
|
||
let rt = tokio::runtime::Builder::new_current_thread() | ||
.enable_all() | ||
.build() | ||
.unwrap(); | ||
|
||
match local.block_on(&rt, tasks) { | ||
Ok(()) => {} | ||
Err(err) => error!("failed to wait for end: {err}"), | ||
} | ||
}); | ||
|
||
let response = match res_rx.await { | ||
Ok(res) => { | ||
let mut rb = HttpResponse::build(res.status()); | ||
|
||
for (k, v) in res.headers() { | ||
rb.append_header((k, v)); | ||
} | ||
|
||
rb.body(res.body().clone()) | ||
} | ||
Err(err) => { | ||
error!("worker fetch error: {}, ensure the worker registered a listener for the 'fetch' event", err); | ||
HttpResponse::InternalServerError().body(err.to_string()) | ||
} | ||
}; | ||
|
||
debug!("handle_request done t={}", start.elapsed().as_millis()); | ||
|
||
debug!("waiting for js worker to finish t={}", start.elapsed().as_millis()); | ||
handle.join().unwrap(); | ||
|
||
response | ||
} | ||
|
||
fn get_path() -> String { | ||
std::env::args() | ||
.nth(1) | ||
.unwrap_or_else(|| String::from("examples/serve.js")) | ||
} | ||
|
||
#[actix_web::main] | ||
async fn main() -> std::io::Result<()> { | ||
if !std::env::var("RUST_LOG").is_ok() { | ||
std::env::set_var("RUST_LOG", "info"); | ||
} | ||
|
||
env_logger::init(); | ||
|
||
debug!("start main"); | ||
|
||
// Check that the path is correct | ||
{ | ||
let path = get_path(); | ||
if !std::path::Path::new(&path).is_file() { | ||
eprintln!("file not found: {}", path); | ||
std::process::exit(1); | ||
} | ||
} | ||
|
||
println!("Listening on http://localhost:8080"); | ||
|
||
HttpServer::new(|| { | ||
App::new() | ||
.app_data(Data::new({ | ||
let path = get_path(); | ||
let url: Url = openworkers_runtime::module_url(path.as_str()); | ||
|
||
AppState { url } | ||
})) | ||
.default_service(web::to(handle_request)) | ||
}) | ||
.bind(("127.0.0.1", 8080))? | ||
.workers(4) | ||
.run() | ||
.await | ||
} |
Oops, something went wrong.