Compare commits

..

2 Commits

Author SHA1 Message Date
Dustin 876c4c188e draft: server: rpc client 2022-01-09 11:30:17 -06:00
Dustin dea3d257ae draft: backend: json rpc 2022-01-09 11:30:17 -06:00
8 changed files with 41 additions and 70 deletions

View File

@ -22,4 +22,4 @@ features = ["chrono"]
[dependencies.rocket] [dependencies.rocket]
version = "^0.5.0-rc.1" version = "^0.5.0-rc.1"
features = ["json", "secrets", "tls"] features = ["json", "secrets", "tls"]

View File

@ -1,27 +1,36 @@
use crate::models::status::DaemonStatus; use crate::models::status::Status;
use crate::rpc::WeywotRpc; use crate::rpc::WeywotRpc;
use chrono::Local; use chrono::{DateTime, Local};
use jsonrpc_core::Result as JsonRpcResult; use jsonrpc_core::Result as JsonRpcResult;
use procfs::process::Process; use procfs::process::Process;
use std::convert::TryInto; use std::convert::TryInto;
use std::error::Error; use std::num::TryFromIntError;
use std::process; use std::process;
pub struct RpcDaemon; pub struct RpcDaemon;
impl WeywotRpc for RpcDaemon { impl WeywotRpc for RpcDaemon {
fn status(&self) -> JsonRpcResult<DaemonStatus> { fn status(&self) -> JsonRpcResult<Status> {
Ok(DaemonStatus { let pid: Result<i32, TryFromIntError> = process::id().try_into();
let runtime: i64 = if let Ok(pid) = pid {
if let Ok(proc) = Process::new(pid) {
let now: DateTime<Local> = Local::now();
if let Ok(starttime) = proc.stat.starttime() {
let etime = now - starttime;
etime.num_seconds()
} else {
0
}
} else {
0
}
} else {
0
};
Ok(Status {
version: env!("CARGO_PKG_VERSION").into(), version: env!("CARGO_PKG_VERSION").into(),
runtime: proc_runtime().unwrap_or(0), runtime: runtime,
}) })
} }
} }
fn proc_runtime() -> Result<i64, Box<dyn Error>> {
let pid: i32 = process::id().try_into()?;
let proc = Process::new(pid)?;
let starttime = proc.stat.starttime()?;
let now = Local::now();
Ok((now - starttime).num_seconds())
}

View File

@ -1,18 +1,7 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Debug, Deserialize, Serialize)] #[derive(Debug, Deserialize, Serialize)]
pub struct DaemonStatus { pub struct Status {
pub version: String, pub version: String,
pub runtime: i64, pub runtime: i64,
} }
#[derive(Debug, Serialize)]
pub struct WebServerStatus {
pub version: String,
}
#[derive(Debug, Serialize)]
pub struct StatusResponse {
pub daemon: DaemonStatus,
pub web: WebServerStatus,
}

View File

@ -1,9 +1,9 @@
use crate::models::status::DaemonStatus; use crate::models::status::Status;
use jsonrpc_core::Result; use jsonrpc_core::Result;
use jsonrpc_derive::rpc; use jsonrpc_derive::rpc;
#[rpc] #[rpc]
pub trait WeywotRpc { pub trait WeywotRpc {
#[rpc(name = "status")] #[rpc(name = "status")]
fn status(&self) -> Result<DaemonStatus>; fn status(&self) -> Result<Status>;
} }

View File

@ -1,8 +1,5 @@
use crate::rpc::gen_client::Client; use crate::rpc::gen_client::Client;
use crate::server::error::{ApiError, ErrorResponse};
use jsonrpc_core_client::transports::ipc::connect; use jsonrpc_core_client::transports::ipc::connect;
use rocket::http::Status as HttpStatus;
use rocket::serde::json::Json;
use std::path::PathBuf; use std::path::PathBuf;
pub struct Context { pub struct Context {
@ -16,16 +13,13 @@ impl Context {
} }
} }
pub async fn client(&self) -> Result<Client, ApiError> { pub async fn client(&self) -> Option<Client> {
match connect(&self.socket_path).await { match connect(&self.socket_path).await {
Ok(client) => Ok(client), Ok(client) => Some(client),
Err(e) => Err(( Err(e) => {
HttpStatus::ServiceUnavailable, eprintln!("{}", e);
Json(ErrorResponse::new(format!( None
"Cannot connect to daemon: {}", }
e
))),
)),
} }
} }
} }

View File

@ -1,18 +0,0 @@
use rocket::http::Status as HttpStatus;
use rocket::serde::json::Json;
use rocket::serde::Serialize;
#[derive(Serialize)]
pub struct ErrorResponse {
pub error: String,
}
pub type ApiError = (HttpStatus, Json<ErrorResponse>);
impl ErrorResponse {
pub fn new<S: Into<String>>(message: S) -> Self {
Self {
error: message.into(),
}
}
}

View File

@ -1,6 +1,5 @@
mod config; mod config;
mod context; mod context;
mod error;
mod routes; mod routes;
use config::Config; use config::Config;

View File

@ -1,18 +1,16 @@
use crate::models::status::{StatusResponse, WebServerStatus}; use crate::models::status::Status;
use crate::server::context::Context; use crate::server::context::Context;
use crate::server::error::ApiError; use rocket::http::Status as HttpStatus;
use rocket::serde::json::Json; use rocket::serde::json::Json;
use rocket::State; use rocket::State;
#[rocket::get("/status")] #[rocket::get("/status")]
pub async fn get_status( pub async fn get_status(
state: &State<Context>, state: &State<Context>,
) -> Result<Json<StatusResponse>, ApiError> { ) -> Result<Json<Status>, HttpStatus> {
let client = state.client().await?; if let Some(client) = state.client().await {
Ok(Json(StatusResponse { Ok(Json(client.status().await.unwrap()))
daemon: client.status().await.unwrap(), } else {
web: WebServerStatus { Err(HttpStatus::ServiceUnavailable)
version: env!("CARGO_PKG_VERSION").into(), }
},
}))
} }