Skip to content

Commit

Permalink
Spawn an actor for each http request. Option web-server.single_actor …
Browse files Browse the repository at this point in the history
…in torchbear.toml
  • Loading branch information
Arnaz87 committed Dec 6, 2018
1 parent 665df51 commit b81bcc2
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 53 deletions.
12 changes: 9 additions & 3 deletions src/bindings/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,15 @@ fn extract_table_from_request(request: &HttpRequest<AppState>, body: String) ->
pub fn handler((request, body): (HttpRequest<AppState>, String)) -> FutureResponse<HttpResponse> {
let table = extract_table_from_request(&request, body);

request.state()
.lua
.send(LuaMessage::Table(table))
let app_state = request.state();

let own_addr = if app_state.lua.is_none() {
Some(app_state.create_addr())
} else { None };

let addr = own_addr.as_ref().unwrap_or_else(|| { app_state.lua.as_ref().unwrap() });

addr.send(LuaMessage::Table(table))
.from_err()
.and_then(|res| match res {
LuaMessage::String(s) => Ok(HttpResponse::Ok().body(s)),
Expand Down
127 changes: 77 additions & 50 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,52 +51,69 @@ use std::io;
use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod};
use serde_json::Value;

type LuaAddr = ::actix::Addr<::actix_lua::LuaActor>;

#[derive(Clone)]
pub struct AppState {
pub lua: ::actix::Addr<::actix_lua::LuaActor>
pub lua: Option<LuaAddr>,
pub init_path: String,
pub settings: Value,
}

fn create_vm(init_path: &str, settings: Value) -> Result<Lua, LuaError> {
let lua = unsafe { Lua::new_with_debug() };

lua.exec::<_, ()>(include_str!("handlers/debug.lua"), None)?;

bindings::tera::init(&lua)?;
bindings::yaml::init(&lua)?;
bindings::json::init(&lua)?;
bindings::uuid::init(&lua)?;
bindings::markdown::init(&lua)?;
bindings::client::init(&lua)?;
bindings::crypto::init(&lua)?;
bindings::stringset::init(&lua)?;
bindings::time::init(&lua)?;
bindings::fs::init(&lua)?;
bindings::select::init(&lua)?;
bindings::git::init(&lua)?;
bindings::regex::init(&lua)?;
bindings::tantivy::init(&lua)?;
bindings::mime::init(&lua)?;
bindings::scl::init(&lua)?;
bindings::heck::init(&lua)?;

// torchbear crashes if there's no log binding
//if cfg!(feature = "log_bindings") {
bindings::log::init(&lua)?;
//}

// torchbear global table
{
let tb_table = lua.create_table()?;
tb_table.set("settings", rlua_serde::to_value(&lua, settings).map_err(LuaError::external)?)?;
tb_table.set("init_filename", init_path)?;
tb_table.set("version", env!("CARGO_PKG_VERSION"))?;
lua.globals().set("torchbear", tb_table)?;
}
impl AppState {
pub fn create_vm (&self) -> Result<Lua, LuaError> {
let lua = unsafe { Lua::new_with_debug() };

lua.exec::<_, ()>(include_str!("handlers/debug.lua"), None)?;

bindings::tera::init(&lua)?;
bindings::yaml::init(&lua)?;
bindings::json::init(&lua)?;
bindings::uuid::init(&lua)?;
bindings::markdown::init(&lua)?;
bindings::client::init(&lua)?;
bindings::crypto::init(&lua)?;
bindings::stringset::init(&lua)?;
bindings::time::init(&lua)?;
bindings::fs::init(&lua)?;
bindings::select::init(&lua)?;
bindings::git::init(&lua)?;
bindings::regex::init(&lua)?;
bindings::tantivy::init(&lua)?;
bindings::mime::init(&lua)?;
bindings::scl::init(&lua)?;
bindings::heck::init(&lua)?;

// torchbear crashes if there's no log binding
//if cfg!(feature = "log_bindings") {
bindings::log::init(&lua)?;
//}

// torchbear global table
{
let tb_table = lua.create_table()?;
tb_table.set("settings", rlua_serde::to_value(&lua, &self.settings).map_err(LuaError::external)?)?;
tb_table.set("init_filename", self.init_path.clone())?;
tb_table.set("version", env!("CARGO_PKG_VERSION"))?;
lua.globals().set("torchbear", tb_table)?;
}

// Lua Bridge
lua.exec::<_, ()>(include_str!("handlers/bridge.lua"), None)?;
// Lua Bridge
lua.exec::<_, ()>(include_str!("handlers/bridge.lua"), None)?;

Ok(lua)
Ok(lua)
}

pub fn create_addr (&self) -> LuaAddr {
let vm = self.create_vm().unwrap();
Arbiter::start(move |_| {
let lua_actor = LuaActorBuilder::new()
.on_handle_with_lua(include_str!("handlers/web_server.lua"))
.build_with_vm(vm)
.unwrap();
lua_actor
})
}
}

//TODO: Implement a better error handler for `ApplicationBuilder` or across torchbear
Expand Down Expand Up @@ -182,17 +199,24 @@ impl ApplicationBuilder {

let sys = actix::System::new("torchbear");

let vm = create_vm(&init_path, general).unwrap();

let addr = Arbiter::start(move |_| {
let lua_actor = LuaActorBuilder::new()
.on_handle_with_lua(include_str!("handlers/web_server.lua"))
.build_with_vm(vm)
.unwrap();
lua_actor
});
let mut app_state = AppState { lua: None, init_path: init_path, settings: general };

if let Some(web) = config.web_server {

let single_actor = match web.get("single_actor").map(|s| { s.as_str() }) {

This comment has been minimized.

Copy link
@dariusc93

dariusc93 Dec 6, 2018

Contributor

You could use as_bool() to get the boolean from it. Maybe so something like

let single_actor = match web.get("single_actor").map(|s| s.as_bool().unwrap_or(false) ) {
                Some(true) => true,
                Some(false) => false,
                None => {
                    println!("Error: Setting web_server.single_actor must be either \"true\" or \"false\"");
                    std::process::exit(1);
                },
            };
Some(Some("true")) => true,
Some(Some("false")) => false,

This comment has been minimized.

Copy link
@naturallymitchell

naturallymitchell Dec 6, 2018

Member

can you make false the default option?

None => false,
_ => {
println!("Error: Setting web_server.single_actor must be either \"true\" or \"false\"");

This comment has been minimized.

Copy link
@naturallymitchell

naturallymitchell Dec 6, 2018

Member

error()

This comment has been minimized.

Copy link
@Arnaz87

Arnaz87 Dec 7, 2018

Author Contributor

error uses the logger to print the message, which is good, but this method of logging config errors is consistent with the way it's being done through the module, eg. line 175 and 195

std::process::exit(1);
},
};

if single_actor {
app_state.lua = Some(app_state.create_addr());
}

log::debug!("web server section in settings, starting seting up web server");
let host = get_or(&web, "address", "0.0.0.0");
let port = get_or(&web, "port", "3000").parse().unwrap_or(3000);
Expand All @@ -212,7 +236,7 @@ impl ApplicationBuilder {
};

let mut server = actix_server::new(move || {
App::with_state(AppState { lua: addr.clone() })
App::with_state(app_state.clone())
.default_resource(|r| r.with(bindings::server::handler))
});

Expand All @@ -229,6 +253,9 @@ impl ApplicationBuilder {
server.start();

let _ = sys.run();
} else {
println!("Non web-server apps not yet supported.");

This comment has been minimized.

Copy link
@naturallymitchell

naturallymitchell Dec 6, 2018

Member

should be error()

std::process::exit(1);
}

}
Expand Down

0 comments on commit b81bcc2

Please sign in to comment.