Skip to content

Commit

Permalink
refactor(cli): drop anyhow
Browse files Browse the repository at this point in the history
  • Loading branch information
mehulmathur001 committed Jun 9, 2024
1 parent 6118a99 commit 882f1e4
Show file tree
Hide file tree
Showing 13 changed files with 133 additions and 64 deletions.
88 changes: 87 additions & 1 deletion src/cli/error.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,90 @@
use crate::core::Errata;
use std::string::FromUtf8Error;

use derive_more::From;
use inquire::InquireError;
use opentelemetry::logs::LogError;
use opentelemetry::metrics::MetricsError;
use opentelemetry::trace::TraceError;
use tokio::task::JoinError;

use crate::core::{rest, Errata};

#[derive(From, thiserror::Error, Debug)]
pub enum Error {
#[error("Metrics Error")]
MetricsError(MetricsError),

#[error("Rest Error")]
RestError(rest::error::Error),

#[error("Errata Error")]
ErrataError(Errata),

#[error("Serde Json Error")]
SerdeJsonError(serde_json::Error),

#[error("IO Error")]
IOError(std::io::Error),

#[error("Telemetry Trace Error : {0}")]
TelemetryTraceError(String),

#[error("Failed to send message")]
MessageSendFailure,

#[error("Hyper Error")]
HyperError(hyper::Error),

#[error("Rustls Error")]
RustlsError(rustls::Error),

#[error("Join Error")]
JoinError(JoinError),

#[error("Opentelemetry Global Error")]
OpentelemetryGlobalError(opentelemetry::global::Error),

#[error("Trace Error")]
TraceError(TraceError),

#[error("Log Error")]
LogError(LogError),

#[error("Utf8 Error")]
Utf8Error(FromUtf8Error),

#[error("Inquire Error")]
InquireError(InquireError),

#[error("Serde Yaml Error")]
SerdeYamlError(serde_yaml::Error),

#[error("Invalid Header Name")]
InvalidHeaderName(hyper::header::InvalidHeaderName),

#[error("Invalid Header Value")]
InvalidHeaderValue(hyper::header::InvalidHeaderValue),

#[error("rquickjs Error")]
RQuickjsError(rquickjs::Error),

#[error("Trying to reinitialize an already initialized QuickJS runtime")]
ReinitializeQuickjsRuntimeError,

#[error("Runtime not initialized")]
RuntimeNotInitializedError,

#[error("Deserialize Failed")]
DeserializeFailed,

#[error("Not a function error")]
NotaFunctionError,

#[error("Init Process Observer Error")]
InitProcessObserverError,
}

pub type Result<A> = std::result::Result<A, Error>;

impl From<rustls::Error> for Errata {
fn from(error: rustls::Error) -> Self {
Expand Down
5 changes: 2 additions & 3 deletions src/cli/javascript/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ mod runtime;

pub use runtime::Runtime;

use crate::cli::Result;
use crate::core::{blueprint, WorkerIO};

pub fn init_worker_io<T, V>(script: blueprint::Script) -> Arc<dyn WorkerIO<T, V> + Send + Sync>
Expand All @@ -18,9 +19,7 @@ where
(Arc::new(Runtime::new(script))) as _
}

fn create_header_map(
headers: BTreeMap<String, String>,
) -> anyhow::Result<reqwest::header::HeaderMap> {
fn create_header_map(headers: BTreeMap<String, String>) -> Result<reqwest::header::HeaderMap> {
let mut header_map = reqwest::header::HeaderMap::new();
for (key, value) in headers.iter() {
let key = HeaderName::from_bytes(key.as_bytes())?;
Expand Down
50 changes: 18 additions & 32 deletions src/cli/javascript/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use std::thread;
use async_graphql_value::ConstValue;
use rquickjs::{Context, Ctx, FromJs, Function, IntoJs, Value};

use crate::cli::{Error, Result};
use crate::core::worker::{Command, Event, WorkerRequest};
use crate::core::{blueprint, WorkerIO};

Expand Down Expand Up @@ -32,7 +33,7 @@ fn setup_builtins(ctx: &Ctx<'_>) -> rquickjs::Result<()> {
}

impl LocalRuntime {
fn try_new(script: blueprint::Script) -> anyhow::Result<Self> {
fn try_new(script: blueprint::Script) -> Result<Self> {
let source = script.source;
let js_runtime = rquickjs::Runtime::new()?;
let context = Context::full(&js_runtime)?;
Expand Down Expand Up @@ -117,15 +118,15 @@ impl WorkerIO<ConstValue, ConstValue> for Runtime {
}
}

fn init_rt(script: blueprint::Script) -> anyhow::Result<()> {
fn init_rt(script: blueprint::Script) -> Result<()> {
// initialize runtime if this is the first call
// exit if failed to initialize
LOCAL_RUNTIME.with(move |cell| {
if cell.borrow().get().is_none() {
LocalRuntime::try_new(script).and_then(|runtime| {
cell.borrow().set(runtime).map_err(|_| {
anyhow::anyhow!("trying to reinitialize an already initialized QuickJS runtime")
})
cell.borrow()
.set(runtime)
.map_err(|_| Error::ReinitializeQuickjsRuntimeError)
})
} else {
Ok(())
Expand All @@ -139,50 +140,35 @@ fn prepare_args<'js>(ctx: &Ctx<'js>, req: WorkerRequest) -> rquickjs::Result<(Va
Ok((object.into_value(),))
}

fn call(name: String, event: Event) -> anyhow::Result<Option<Command>> {
fn call(name: String, event: Event) -> Result<Option<Command>> {
LOCAL_RUNTIME.with_borrow_mut(|cell| {
let runtime = cell
.get_mut()
.ok_or(anyhow::anyhow!("JS runtime not initialized"))?;
let runtime = cell.get_mut().ok_or(Error::RuntimeNotInitializedError)?;
runtime.0.with(|ctx| match event {
Event::Request(req) => {
let fn_as_value = ctx
.globals()
.get::<&str, Function>(name.as_str())
.map_err(|_| anyhow::anyhow!("globalThis not initialized"))?;
let fn_as_value = ctx.globals().get::<&str, Function>(name.as_str())?;

let function = fn_as_value
.as_function()
.ok_or(anyhow::anyhow!("`{name}` is not a function"))?;
let function = fn_as_value.as_function().ok_or(Error::NotaFunctionError)?;

let args = prepare_args(&ctx, req)?;
let command: Option<Value> = function.call(args).ok();
command
.map(|output| Command::from_js(&ctx, output))
.transpose()
.map_err(|e| anyhow::anyhow!("deserialize failed: {e}"))
.map_err(|_| Error::DeserializeFailed)
}
})
})
}

fn execute_inner(name: String, value: String) -> anyhow::Result<ConstValue> {
fn execute_inner(name: String, value: String) -> Result<ConstValue> {
LOCAL_RUNTIME.with_borrow_mut(|cell| {
let runtime = cell
.get_mut()
.ok_or(anyhow::anyhow!("JS runtime not initialized"))?;
let runtime = cell.get_mut().ok_or(Error::RuntimeNotInitializedError)?;
runtime.0.with(|ctx| {
let fn_as_value = ctx
.globals()
.get::<_, rquickjs::Function>(&name)
.map_err(|_| anyhow::anyhow!("globalThis not initialized"))?;

let function = fn_as_value
.as_function()
.ok_or(anyhow::anyhow!("`{}` is not a function", name))?;
let val: String = function.call((value, ))
.map_err(|_| anyhow::anyhow!("unable to parse value from js function: {} maybe because it's not returning a string?", name,))?;
Ok::<_, anyhow::Error>(serde_json::from_str(&val)?)
let fn_as_value = ctx.globals().get::<_, rquickjs::Function>(&name)?;

let function = fn_as_value.as_function().ok_or(Error::NotaFunctionError)?;
let val: String = function.call((value,))?;
Ok::<_, Error>(serde_json::from_str(&val)?)
})
})
}
6 changes: 3 additions & 3 deletions src/cli/metrics.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use anyhow::{anyhow, Result};

use super::{Error, Result};
use crate::core::runtime::TargetRuntime;

fn cache_metrics(runtime: &TargetRuntime) -> Result<()> {
Expand All @@ -22,7 +21,8 @@ fn cache_metrics(runtime: &TargetRuntime) -> Result<()> {
fn process_resources_metrics() -> Result<()> {
let meter = opentelemetry::global::meter("process-resources");

opentelemetry_system_metrics::init_process_observer(meter).map_err(|err| anyhow!(err))
opentelemetry_system_metrics::init_process_observer(meter)
.map_err(|_| Error::InitProcessObserverError)
}

pub fn init_metrics(runtime: &TargetRuntime) -> Result<()> {
Expand Down
1 change: 1 addition & 0 deletions src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ pub mod telemetry;
pub mod runtime;
pub(crate) mod update_checker;

pub use error::{Error, Result};
pub use tc::run;
5 changes: 3 additions & 2 deletions src/cli/runtime/file.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use tokio::io::{AsyncReadExt, AsyncWriteExt};

use crate::cli::Result;
use crate::core::{Errata, FileIO};

#[derive(Clone)]
Expand All @@ -11,14 +12,14 @@ impl NativeFileIO {
}
}

async fn read(path: &str) -> anyhow::Result<String> {
async fn read(path: &str) -> Result<String> {
let mut file = tokio::fs::File::open(path).await?;
let mut buffer = Vec::new();
file.read_to_end(&mut buffer).await?;
Ok(String::from_utf8(buffer)?)
}

async fn write<'a>(path: &'a str, content: &'a [u8]) -> anyhow::Result<()> {
async fn write<'a>(path: &'a str, content: &'a [u8]) -> Result<()> {
let mut file = tokio::fs::File::create(path).await?;
file.write_all(content).await?;
Ok(())
Expand Down
11 changes: 5 additions & 6 deletions src/cli/server/http_1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,20 @@ use hyper::service::{make_service_fn, service_fn};
use tokio::sync::oneshot;

use super::server_config::ServerConfig;
use crate::cli::{Error, Result};
use crate::core::async_graphql_hyper::{GraphQLBatchRequest, GraphQLRequest};
use crate::core::http::handle_request;
use crate::core::Errata;

pub async fn start_http_1(
sc: Arc<ServerConfig>,
server_up_sender: Option<oneshot::Sender<()>>,
) -> anyhow::Result<()> {
) -> Result<()> {
let addr = sc.addr();
let make_svc_single_req = make_service_fn(|_conn| {
let state = Arc::clone(&sc);
async move {
Ok::<_, anyhow::Error>(service_fn(move |req| {
Ok::<_, Error>(service_fn(move |req| {
handle_request::<GraphQLRequest>(req, state.app_ctx.clone())
}))
}
Expand All @@ -25,7 +26,7 @@ pub async fn start_http_1(
let make_svc_batch_req = make_service_fn(|_conn| {
let state = Arc::clone(&sc);
async move {
Ok::<_, anyhow::Error>(service_fn(move |req| {
Ok::<_, Error>(service_fn(move |req| {
handle_request::<GraphQLBatchRequest>(req, state.app_ctx.clone())
}))
}
Expand All @@ -36,9 +37,7 @@ pub async fn start_http_1(
super::log_launch(sc.as_ref());

if let Some(sender) = server_up_sender {
sender
.send(())
.or(Err(anyhow::anyhow!("Failed to send message")))?;
sender.send(()).or(Err(Error::MessageSendFailure))?;
}

let server: std::prelude::v1::Result<(), hyper::Error> =
Expand Down
11 changes: 5 additions & 6 deletions src/cli/server/http_2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use rustls_pki_types::{CertificateDer, PrivateKeyDer};
use tokio::sync::oneshot;

use super::server_config::ServerConfig;
use crate::cli::{Error, Result};
use crate::core::async_graphql_hyper::{GraphQLBatchRequest, GraphQLRequest};
use crate::core::http::handle_request;
use crate::core::Errata;
Expand All @@ -18,7 +19,7 @@ pub async fn start_http_2(
cert: Vec<CertificateDer<'static>>,
key: Arc<PrivateKeyDer<'static>>,
server_up_sender: Option<oneshot::Sender<()>>,
) -> anyhow::Result<()> {
) -> Result<()> {
let addr = sc.addr();
let incoming = AddrIncoming::bind(&addr)?;
let acceptor = TlsAcceptor::builder()
Expand All @@ -28,7 +29,7 @@ pub async fn start_http_2(
let make_svc_single_req = make_service_fn(|_conn| {
let state = Arc::clone(&sc);
async move {
Ok::<_, anyhow::Error>(service_fn(move |req| {
Ok::<_, Error>(service_fn(move |req| {
handle_request::<GraphQLRequest>(req, state.app_ctx.clone())
}))
}
Expand All @@ -37,7 +38,7 @@ pub async fn start_http_2(
let make_svc_batch_req = make_service_fn(|_conn| {
let state = Arc::clone(&sc);
async move {
Ok::<_, anyhow::Error>(service_fn(move |req| {
Ok::<_, Error>(service_fn(move |req| {
handle_request::<GraphQLBatchRequest>(req, state.app_ctx.clone())
}))
}
Expand All @@ -48,9 +49,7 @@ pub async fn start_http_2(
super::log_launch(sc.as_ref());

if let Some(sender) = server_up_sender {
sender
.send(())
.or(Err(anyhow::anyhow!("Failed to send message")))?;
sender.send(()).or(Err(Error::MessageSendFailure))?;
}

let server: std::prelude::v1::Result<(), hyper::Error> =
Expand Down
2 changes: 1 addition & 1 deletion src/cli/server/http_server.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use std::ops::Deref;
use std::sync::Arc;

use anyhow::Result;
use tokio::sync::oneshot::{self};

use super::http_1::start_http_1;
use super::http_2::start_http_2;
use super::server_config::ServerConfig;
use crate::cli::telemetry::init_opentelemetry;
use crate::cli::Result;
use crate::core::blueprint::{Blueprint, Http};
use crate::core::config::ConfigModule;
use crate::core::Errata;
Expand Down
6 changes: 2 additions & 4 deletions src/cli/server/server_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use std::sync::Arc;
use async_graphql_extension_apollo_tracing::ApolloTracing;

use crate::cli::runtime::init;
use crate::cli::Result;
use crate::core::blueprint::telemetry::TelemetryExporter;
use crate::core::blueprint::{Blueprint, Http};
use crate::core::http::AppContext;
Expand All @@ -16,10 +17,7 @@ pub struct ServerConfig {
}

impl ServerConfig {
pub async fn new(
blueprint: Blueprint,
endpoints: EndpointSet<Unchecked>,
) -> anyhow::Result<Self> {
pub async fn new(blueprint: Blueprint, endpoints: EndpointSet<Unchecked>) -> Result<Self> {
let mut rt = init(&blueprint);

let mut extensions = vec![];
Expand Down
3 changes: 1 addition & 2 deletions src/cli/tc.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use std::fs;
use std::path::Path;

use anyhow::Result;
use clap::Parser;
use convert_case::{Case, Casing};
use dotenvy::dotenv;
Expand All @@ -10,7 +9,7 @@ use lazy_static::lazy_static;
use stripmargin::StripMargin;

use super::command::{Cli, Command};
use super::update_checker;
use super::{update_checker, Result};
use crate::cli;
use crate::cli::fmt::Fmt;
use crate::cli::server::Server;
Expand Down
Loading

0 comments on commit 882f1e4

Please sign in to comment.