Skip to content

Commit

Permalink
Better error reporting in query interface
Browse files Browse the repository at this point in the history
  • Loading branch information
tailhook committed Jul 4, 2018
1 parent 4909fd3 commit 3776f5e
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 15 deletions.
1 change: 1 addition & 0 deletions example-configs/wasm-with-query/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ version = "0.1.0"

[dependencies]
serde = "1.0.0"
serde_derive = "1.0.69"
serde_json = "1.0.0"
39 changes: 32 additions & 7 deletions example-configs/wasm-with-query/src/bin/query.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
extern crate serde;
#[macro_use] extern crate serde_derive;
#[macro_use] extern crate serde_json;

use std::mem;
Expand All @@ -14,6 +15,21 @@ extern {
file_ptr: *const u8, file_len: usize, line: u32);
}

#[derive(Debug, Serialize)]
enum ErrorKind {
Serialize,
Deserialize,
Internal,
}

#[derive(Debug, Serialize)]
struct QueryError {
kind: ErrorKind,
message: String,
causes: Option<Vec<String>>,
backtrace: Option<String>,
}

fn main() {
set_hook(Box::new(|panic_info| {
let payload = panic_info.payload();
Expand Down Expand Up @@ -68,19 +84,28 @@ fn _wrapper<'x, F, S, D>(data: &'x [u8], f: F) -> Vec<u8>
let input = match from_slice(data) {
Ok(inp) => inp,
Err(e) => {
return to_vec(&json!({
"Err": format!("Error deserializing input: {}", e),
})).expect("should serialize standard json");
return to_vec(
&Err::<(), _>(QueryError {
kind: ErrorKind::Deserialize,
message: e.to_string(),
causes: None,
backtrace: None,
})
).expect("should serialize standard json");
}
};
let result = f(input);
match to_vec(&result) {
Ok(result) => result,
Err(e) => {
// TODO(pc) log error
return to_vec(&json!({
"Err": format!("Error serializing output: {}", e),
})).expect("should serialize standard json");
return to_vec(
&Err::<(), _>(QueryError {
kind: ErrorKind::Serialize,
message: e.to_string(),
causes: None,
backtrace: None,
})
).expect("should serialize standard json");
}
}
}
Expand Down
64 changes: 56 additions & 8 deletions src/daemon/query/wasm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::collections::BTreeMap;
use std::sync::Arc;
use std::path::Path;

use failure::{Error, err_msg};
use failure::Error;
use query::Settings;
use serde_json::{Value as Json};

Expand All @@ -26,17 +26,44 @@ pub struct RolesQuery<'a> {
deployment_id: &'a str,
}

#[derive(Debug, PartialEq, Eq, Hash)]
enum ErrorKind {
Serialize,
Deserialize,
Internal,
Other(String)
}

#[derive(Debug, Fail, Deserialize)]
#[fail(display="query error {:?}: {}", kind, message)]
struct QueryError {
kind: ErrorKind,
message: String,
causes: Option<Vec<String>>,
backtrace: Option<String>,
}

#[derive(Debug, Fail, Deserialize)]
#[serde(untagged)]
enum CatchAllError {
#[fail(display="{}", _0)]
Known(QueryError),
#[fail(display="unknown error: {:?}", _0)]
Unknown(Json),
}

impl Responder {
pub fn new(schedule: &Arc<Schedule>, settings: &Settings,
file: &Path)
-> Result<Responder, Error>
{
let mut wasm = Program::read(file)?;
let init_res: Result<(), String> = wasm.json_call("init", &QueryInit {
schedule: &*schedule,
hostname: &settings.hostname,
})?;
init_res.map_err(|e| err_msg(e))?;
let init_res: Result<(), CatchAllError> = wasm.json_call("init",
&QueryInit {
schedule: &*schedule,
hostname: &settings.hostname,
})?;
init_res?;
Ok(Responder {
schedule: schedule.clone(),
wasm,
Expand All @@ -46,14 +73,35 @@ impl Responder {
pub fn render_roles(&mut self, id: &str)
-> Result<BTreeMap<String, Json>, Error>
{
let result: Result<_, String>;
let result: Result<_, CatchAllError>;
result = self.wasm.json_call("render_roles", &RolesQuery {
deployment_id: id,
})?;
return result.map_err(|e| err_msg(e));
return Ok(result?);
}

pub fn schedule(&self) -> Arc<Schedule> {
self.schedule.clone()
}
}

mod serde {
use serde::de::{Deserialize, Deserializer};
use super::ErrorKind;

impl<'de> Deserialize<'de> for ErrorKind {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer<'de>
{
use super::ErrorKind::*;

let s = String::deserialize(deserializer)?;
Ok(match s.as_str() {
"Serialize" => Serialize,
"Deserialize" => Deserialize,
"Internal" => Internal,
_ => Other(s),
})
}
}
}

0 comments on commit 3776f5e

Please sign in to comment.