refactor: let state use either local or backend
All checks were successful
continuous-integration/drone/push Build is passing

Signed-off-by: kjuulh <contact@kjuulh.io>
This commit is contained in:
Kasper Juul Hermansen 2024-05-12 15:54:03 +02:00
parent 9cb3296cec
commit 2d63d3ad4c
Signed by: kjuulh
GPG Key ID: 57B6E1465221F912
6 changed files with 68 additions and 20 deletions

View File

@ -24,13 +24,8 @@ impl UpdateGraphCommand {
let now = std::time::SystemTime::now(); let now = std::time::SystemTime::now();
dispatch.send(Msg::GraphUpdated(GraphUpdatedEvent::Initiated)); dispatch.send(Msg::GraphUpdated(GraphUpdatedEvent::Initiated));
match self match self.querier.get_async(&root, path).await {
.querier Ok(Some(graph)) => {
.get_async(&root, path)
.await
.ok_or(anyhow::anyhow!("failed to find path"))
{
Ok(graph) => {
dispatch.send(Msg::GraphUpdated(GraphUpdatedEvent::Optimistic( dispatch.send(Msg::GraphUpdated(GraphUpdatedEvent::Optimistic(
graph.clone(), graph.clone(),
))); )));
@ -42,6 +37,9 @@ impl UpdateGraphCommand {
dispatch.send(Msg::GraphUpdated(GraphUpdatedEvent::Success(graph))) dispatch.send(Msg::GraphUpdated(GraphUpdatedEvent::Success(graph)))
} }
Ok(None) => dispatch.send(Msg::GraphUpdated(GraphUpdatedEvent::Failure(
"graph was not found user root".into(),
))),
Err(e) => dispatch.send(Msg::GraphUpdated(GraphUpdatedEvent::Failure( Err(e) => dispatch.send(Msg::GraphUpdated(GraphUpdatedEvent::Failure(
format!("{e}"), format!("{e}"),
))), ))),

View File

@ -114,7 +114,7 @@ impl<'a> GraphExplorer<'a> {
.map(|p| p.split('.').collect::<Vec<_>>()) .map(|p| p.split('.').collect::<Vec<_>>())
.unwrap_or_default(), .unwrap_or_default(),
) )
.await .await?
.ok_or(anyhow::anyhow!("graph should've had an item"))?; .ok_or(anyhow::anyhow!("graph should've had an item"))?;
self.inner.graph = Some(graph); self.inner.graph = Some(graph);

View File

@ -13,12 +13,21 @@ pub struct State {
pub querier: Querier, pub querier: Querier,
} }
pub enum Backend {
Local,
Remote,
}
impl State { impl State {
pub fn new() -> anyhow::Result<Self> { pub async fn new(backend: Backend) -> anyhow::Result<Self> {
let storage = Storage::new(); let storage = Storage::new();
let engine = storage.load()?; let engine = storage.load()?;
let events = Events::default(); let events = Events::default();
let engine = SharedEngine::from(engine); let engine = SharedEngine::from(engine);
let querier = match backend {
Backend::Local => Querier::local(&engine),
Backend::Remote => Querier::remote().await?,
};
Ok(Self { Ok(Self {
engine: engine.clone(), engine: engine.clone(),
@ -26,7 +35,7 @@ impl State {
events: events.clone(), events: events.clone(),
commander: Commander::new(engine.clone(), storage, events)?, commander: Commander::new(engine.clone(), storage, events)?,
querier: Querier::local(&engine), querier,
}) })
} }
} }

View File

@ -8,6 +8,7 @@ mod remote;
#[derive(Clone)] #[derive(Clone)]
enum QuerierVariant { enum QuerierVariant {
Local(local::Querier), Local(local::Querier),
Remote(remote::Querier),
} }
#[derive(Clone)] #[derive(Clone)]
@ -22,6 +23,12 @@ impl Querier {
} }
} }
pub async fn remote() -> anyhow::Result<Self> {
Ok(Self {
variant: QuerierVariant::Remote(remote::Querier::new().await?),
})
}
pub fn get( pub fn get(
&self, &self,
root: &str, root: &str,
@ -29,6 +36,7 @@ impl Querier {
) -> Option<GraphItem> { ) -> Option<GraphItem> {
match &self.variant { match &self.variant {
QuerierVariant::Local(querier) => querier.get(root, path), QuerierVariant::Local(querier) => querier.get(root, path),
QuerierVariant::Remote(_) => todo!(),
} }
} }
@ -36,15 +44,24 @@ impl Querier {
&self, &self,
root: &str, root: &str,
path: impl IntoIterator<Item = impl Into<String>>, path: impl IntoIterator<Item = impl Into<String>>,
) -> Option<GraphItem> { ) -> anyhow::Result<Option<GraphItem>> {
match &self.variant { match &self.variant {
QuerierVariant::Local(querier) => querier.get(root, path), QuerierVariant::Local(querier) => Ok(querier.get(root, path)),
QuerierVariant::Remote(querier) => querier.get(root, path).await,
} }
} }
pub fn get_available_roots(&self) -> Option<Vec<String>> { pub fn get_available_roots(&self) -> Option<Vec<String>> {
match &self.variant { match &self.variant {
QuerierVariant::Local(querier) => querier.get_available_roots(), QuerierVariant::Local(querier) => querier.get_available_roots(),
QuerierVariant::Remote(_) => todo!(),
}
}
pub async fn get_available_roots_async(&self) -> anyhow::Result<Option<Vec<String>>> {
match &self.variant {
QuerierVariant::Local(querier) => Ok(querier.get_available_roots()),
QuerierVariant::Remote(querier) => Ok(querier.get_available_roots().await),
} }
} }
} }

View File

@ -6,6 +6,7 @@ use itertools::Itertools;
use tonic::transport::Channel; use tonic::transport::Channel;
#[allow(dead_code)] #[allow(dead_code)]
#[derive(Clone)]
pub struct Querier { pub struct Querier {
channel: Channel, channel: Channel,
} }

View File

@ -1,13 +1,34 @@
use std::net::SocketAddr; use std::net::SocketAddr;
use clap::{Parser, Subcommand}; use clap::{Parser, Subcommand, ValueEnum};
use hyperlog_tui::{commander, core_state::State}; use hyperlog_tui::{
commander,
core_state::{Backend, State},
};
#[derive(Parser)] #[derive(Parser)]
#[command(author, version, about, long_about = None)] #[command(author, version, about, long_about = None)]
struct Command { struct Command {
#[command(subcommand)] #[command(subcommand)]
command: Option<Commands>, command: Option<Commands>,
#[arg(long, default_value = "local")]
backend: BackendArg,
}
#[derive(ValueEnum, Clone)]
enum BackendArg {
Local,
Remote,
}
impl From<BackendArg> for Backend {
fn from(value: BackendArg) -> Self {
match value {
BackendArg::Local => Backend::Local,
BackendArg::Remote => Backend::Remote,
}
}
} }
#[derive(Subcommand)] #[derive(Subcommand)]
@ -73,6 +94,8 @@ pub async fn execute() -> anyhow::Result<()> {
tracing_subscriber::fmt::init(); tracing_subscriber::fmt::init();
} }
let backend = cli.backend;
match cli.command { match cli.command {
#[cfg(feature = "include_server")] #[cfg(feature = "include_server")]
Some(Commands::Serve { Some(Commands::Serve {
@ -90,7 +113,7 @@ pub async fn execute() -> anyhow::Result<()> {
.await?; .await?;
} }
Some(Commands::Exec { commands }) => { Some(Commands::Exec { commands }) => {
let state = State::new()?; let state = State::new(backend.into()).await?;
match commands { match commands {
ExecCommands::CreateRoot { root } => state ExecCommands::CreateRoot { root } => state
.commander .commander
@ -109,7 +132,7 @@ pub async fn execute() -> anyhow::Result<()> {
} }
} }
Some(Commands::Query { commands }) => { Some(Commands::Query { commands }) => {
let state = State::new()?; let state = State::new(backend.into()).await?;
match commands { match commands {
QueryCommands::Get { root, path } => { QueryCommands::Get { root, path } => {
let res = state.querier.get( let res = state.querier.get(
@ -126,23 +149,23 @@ pub async fn execute() -> anyhow::Result<()> {
} }
} }
Some(Commands::CreateRoot { name }) => { Some(Commands::CreateRoot { name }) => {
let state = State::new()?; let state = State::new(backend.into()).await?;
state state
.commander .commander
.execute(commander::Command::CreateRoot { root: name })?; .execute(commander::Command::CreateRoot { root: name })?;
println!("Root was successfully created, now run:\n\n$ hyperlog"); println!("Root was successfully created, now run:\n\n$ hyperlog");
} }
Some(Commands::Info {}) => { Some(Commands::Info {}) => {
let state = State::new()?; let state = State::new(backend.into()).await?;
println!("graph stored at: {}", state.storage.info()?) println!("graph stored at: {}", state.storage.info()?)
} }
Some(Commands::ClearLock {}) => { Some(Commands::ClearLock {}) => {
let state = State::new()?; let state = State::new(backend.into()).await?;
state.storage.clear_lock_file(); state.storage.clear_lock_file();
println!("cleared lock file"); println!("cleared lock file");
} }
None => { None => {
let state = State::new()?; let state = State::new(backend.into()).await?;
hyperlog_tui::execute(state).await?; hyperlog_tui::execute(state).await?;
} }
} }