Skip to content

Commit be4b5ed

Browse files
committed
ref(daemon): organization
1 parent 7da58b6 commit be4b5ed

File tree

10 files changed

+179
-179
lines changed

10 files changed

+179
-179
lines changed

lua/xcodebase/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use mlua::lua_module;
22
use mlua::prelude::*;
3-
use xcodebase::Daemon;
3+
use xcodebase::daemon::Daemon;
44

55
#[lua_module]
66
fn libxcodebase(lua: &Lua) -> LuaResult<LuaTable> {

src/daemon.rs

Lines changed: 67 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
//! Handle requests from neovim and manage dev workflow
2-
use anyhow::{bail, Context, Result};
32
mod requests;
43
pub mod state;
54

@@ -8,55 +7,71 @@ pub use requests::*;
87
#[cfg(feature = "daemon")]
98
pub use state::DaemonState;
109

10+
#[cfg(feature = "lua")]
11+
use crate::util::mlua::LuaExtension;
12+
13+
#[cfg(feature = "lua")]
14+
use mlua::prelude::*;
15+
16+
#[cfg(feature = "daemon")]
17+
use anyhow::Result;
18+
1119
pub const DAEMON_SOCKET_PATH: &str = "/tmp/xcodebase-daemon.socket";
1220
pub const DAEMON_BINARY: &str =
1321
"/Users/tami5/repos/neovim/xcodebase.nvim/target/debug/xcodebase-daemon";
1422

1523
/// Representation of daemon
16-
pub struct Daemon {
17-
#[cfg(feature = "daemon")]
18-
pub state: std::sync::Arc<tokio::sync::Mutex<state::DaemonStateData>>,
19-
#[cfg(feature = "daemon")]
20-
pub listener: tokio::net::UnixListener,
24+
pub struct Daemon;
25+
26+
/// Requirement for daemon actions
27+
#[cfg(feature = "daemon")]
28+
#[async_trait::async_trait]
29+
pub trait DaemonRequestHandler<T> {
30+
async fn handle(&self, state: DaemonState) -> Result<()>;
31+
fn parse(args: Vec<&str>) -> Result<T>;
2132
}
2233

23-
impl Daemon {
24-
#[cfg(feature = "daemon")]
25-
pub fn new() -> Self {
26-
Self {
27-
state: Default::default(),
28-
listener: tokio::net::UnixListener::bind(DAEMON_SOCKET_PATH).unwrap(),
29-
}
30-
}
34+
/// Representations of all the supported daemon requests
35+
#[derive(Debug)]
36+
pub enum DaemonRequest {
37+
Build(Build),
38+
Run(Run),
39+
RenameFile(RenameFile),
40+
Register(Register),
41+
Drop(Drop),
42+
}
3143

32-
/// Spawn new instance of the server via running binaray is a child process
33-
pub fn spawn() -> Result<()> {
34-
std::process::Command::new(DAEMON_BINARY)
35-
.spawn()
36-
.context("Unable to start background instance using daemon binaray")
37-
.map(|_| ())
44+
#[cfg(feature = "daemon")]
45+
impl DaemonRequest {
46+
/// Handle daemon request
47+
pub async fn handle(&self, state: DaemonState) -> Result<()> {
48+
match self {
49+
DaemonRequest::Build(c) => c.handle(state).await,
50+
DaemonRequest::Run(c) => c.handle(state).await,
51+
DaemonRequest::RenameFile(c) => c.handle(state).await,
52+
DaemonRequest::Register(c) => c.handle(state).await,
53+
DaemonRequest::Drop(c) => c.handle(state).await,
54+
}
3855
}
3956

40-
/// Pass args to running daemon
41-
pub fn execute(args: &[&str]) -> Result<()> {
42-
use std::io::Write;
43-
match std::os::unix::net::UnixStream::connect(DAEMON_SOCKET_PATH) {
44-
Ok(mut stream) => {
45-
stream.write_all(args.join(" ").as_str().as_ref())?;
46-
stream.flush().context("Fail to flush stream!")
47-
}
48-
Err(e) => bail!("Fail to execute {:#?}: {e}", args),
49-
}
57+
/// Parse [`super::Daemon`] request from string
58+
pub fn parse(str: &str) -> Result<Self> {
59+
let mut args = str.split(" ").collect::<Vec<&str>>();
60+
Ok(match args.remove(0) {
61+
Build::KEY => Self::Build(Build::parse(args)?),
62+
Run::KEY => Self::Run(Run::parse(args)?),
63+
RenameFile::KEY => Self::RenameFile(RenameFile::parse(args)?),
64+
Register::KEY => Self::Register(Register::parse(args)?),
65+
Drop::KEY => Self::Drop(Drop::parse(args)?),
66+
cmd => anyhow::bail!("Unknown command messsage: {cmd}"),
67+
})
5068
}
5169
}
5270

53-
#[cfg(feature = "lua")]
54-
use crate::util::mlua::LuaExtension;
55-
5671
#[cfg(feature = "lua")]
5772
impl Daemon {
5873
/// Representation of daemon table in lua
59-
pub fn lua(lua: &mlua::Lua) -> mlua::Result<mlua::Table> {
74+
pub fn lua(lua: &mlua::Lua) -> LuaResult<LuaTable> {
6075
let table = lua.create_table()?;
6176
table.set("is_running", lua.create_function(Self::is_running)?)?;
6277
table.set("ensure", lua.create_function(Self::ensure)?)?;
@@ -66,22 +81,37 @@ impl Daemon {
6681
}
6782

6883
/// Check if Daemon is running
69-
pub fn is_running(_: &mlua::Lua, _: ()) -> mlua::Result<bool> {
84+
pub fn is_running(_: &mlua::Lua, _: ()) -> LuaResult<bool> {
7085
match std::os::unix::net::UnixStream::connect(DAEMON_SOCKET_PATH) {
7186
Ok(stream) => Ok(stream.shutdown(std::net::Shutdown::Both).ok().is_some()),
7287
Err(_) => Ok(false),
7388
}
7489
}
7590

7691
/// Ensure that daemon is currently running in background
77-
pub fn ensure(lua: &mlua::Lua, _: ()) -> mlua::Result<bool> {
92+
pub fn ensure(lua: &mlua::Lua, _: ()) -> LuaResult<bool> {
7893
if Self::is_running(lua, ()).unwrap() {
7994
Ok(false)
80-
} else if Self::spawn().is_ok() {
95+
} else if std::process::Command::new(DAEMON_BINARY).spawn().is_ok() {
8196
lua.info("Spawned Background Server")?;
8297
Ok(true)
8398
} else {
8499
panic!("Unable to spawn background server");
85100
}
86101
}
102+
103+
/// Pass args to running daemon
104+
pub fn execute(args: &[&str]) -> LuaResult<()> {
105+
use std::io::Write;
106+
match std::os::unix::net::UnixStream::connect(DAEMON_SOCKET_PATH) {
107+
Ok(mut stream) => {
108+
stream.write_all(args.join(" ").as_str().as_ref())?;
109+
stream.flush().map_err(mlua::Error::external)
110+
}
111+
Err(e) => Err(mlua::Error::external(format!(
112+
"Fail to execute {:#?}: {e}",
113+
args
114+
))),
115+
}
116+
}
87117
}

src/daemon/bin.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1+
use std::sync::Arc;
2+
13
use tokio::io::AsyncReadExt;
4+
use tokio::sync::Mutex;
25
use xcodebase::util::tracing::install_tracing;
36
use xcodebase::{daemon::*, util::watch};
47

@@ -12,11 +15,12 @@ async fn main() -> anyhow::Result<()> {
1215

1316
tracing::info!("Started");
1417

15-
let daemon = Daemon::new();
18+
let state: Arc<Mutex<state::DaemonStateData>> = Default::default();
19+
let listener = tokio::net::UnixListener::bind(DAEMON_SOCKET_PATH).unwrap();
1620

1721
loop {
18-
let state = daemon.state.clone();
19-
let (mut s, _) = daemon.listener.accept().await.unwrap();
22+
let state = state.clone();
23+
let (mut s, _) = listener.accept().await.unwrap();
2024
tokio::spawn(async move {
2125
let mut string = String::default();
2226

src/daemon/requests.rs

Lines changed: 0 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
use anyhow::Result;
2-
31
mod build;
42
mod drop;
53
mod register;
@@ -11,49 +9,3 @@ pub use drop::Drop;
119
pub use register::Register;
1210
pub use rename_file::RenameFile;
1311
pub use run::Run;
14-
15-
/// Requirement for daemon actions
16-
#[async_trait::async_trait]
17-
#[cfg(feature = "daemon")]
18-
pub trait DaemonRequestHandler {
19-
async fn handle(&self, state: super::DaemonState) -> Result<()>;
20-
}
21-
22-
/// Representations of all the supported daemon requests
23-
#[derive(Debug)]
24-
pub enum DaemonRequest {
25-
Build(Build),
26-
Run(Run),
27-
RenameFile(RenameFile),
28-
Register(Register),
29-
Drop(Drop),
30-
}
31-
32-
impl DaemonRequest {
33-
#[cfg(feature = "daemon")]
34-
/// Handle daemon request
35-
pub async fn handle(&self, state: super::DaemonState) -> Result<()> {
36-
use DaemonRequest::*;
37-
38-
match self {
39-
Build(c) => c.handle(state).await,
40-
Run(c) => c.handle(state).await,
41-
RenameFile(c) => c.handle(state).await,
42-
Register(c) => c.handle(state).await,
43-
Drop(c) => c.handle(state).await,
44-
}
45-
}
46-
47-
/// Parse [`super::Daemon`] request from string
48-
pub fn parse(str: &str) -> Result<Self> {
49-
let mut args = str.split(" ").collect::<Vec<&str>>();
50-
Ok(match args.remove(0) {
51-
Build::KEY => Self::Build(args.try_into()?),
52-
Run::KEY => Self::Run(args.try_into()?),
53-
RenameFile::KEY => Self::RenameFile(args.try_into()?),
54-
Register::KEY => Self::Register(args.try_into()?),
55-
Drop::KEY => Self::Drop(args.try_into()?),
56-
cmd => anyhow::bail!("Unknown command messsage: {cmd}"),
57-
})
58-
}
59-
}

src/daemon/requests/build.rs

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1+
#[cfg(feature = "mlua")]
12
use crate::daemon::Daemon;
3+
4+
#[cfg(feature = "daemon")]
5+
use crate::daemon::{DaemonRequestHandler, DaemonState};
6+
7+
#[cfg(feature = "daemon")]
28
use anyhow::Result;
39

410
/// Build a project.
@@ -9,45 +15,41 @@ pub struct Build {
915
pub scheme: Option<String>,
1016
}
1117

18+
impl Build {
19+
pub const KEY: &'static str = "build";
20+
}
21+
1222
// TODO: Implement build command
1323
// On neovim side:
1424
// - Call the command after picking the target. If their is only a single target then just use that
1525
// - This requires somehow given the client all information it needs in order present the user
1626
// with the options needed to build
1727
#[cfg(feature = "daemon")]
1828
#[async_trait::async_trait]
19-
impl crate::daemon::DaemonRequestHandler for Build {
20-
async fn handle(&self, _state: crate::daemon::DaemonState) -> Result<()> {
21-
tracing::info!("build command");
22-
Ok(())
23-
}
24-
}
25-
26-
impl TryFrom<Vec<&str>> for Build {
27-
type Error = anyhow::Error;
28-
29-
fn try_from(_args: Vec<&str>) -> Result<Self, Self::Error> {
29+
impl DaemonRequestHandler<Build> for Build {
30+
fn parse(_args: Vec<&str>) -> Result<Self> {
3031
Ok(Self {
3132
target: None,
3233
configuration: None,
3334
scheme: None,
3435
})
3536
}
36-
}
3737

38-
impl Build {
39-
pub const KEY: &'static str = "build";
40-
41-
pub fn request(target: &str, configuration: &str, scheme: &str) -> Result<()> {
42-
Daemon::execute(&[KEY, target, configuration, scheme])
38+
async fn handle(&self, _state: DaemonState) -> Result<()> {
39+
tracing::info!("build command");
40+
Ok(())
4341
}
4442
}
4543

44+
#[cfg(feature = "lua")]
4645
impl Build {
47-
#[cfg(feature = "lua")]
4846
pub fn lua(lua: &mlua::Lua, (t, c, s): (String, String, String)) -> mlua::Result<()> {
4947
use crate::util::mlua::LuaExtension;
5048
lua.trace(format!("Build (target: {t} configuration: {c}, scheme: {s})").as_ref())?;
5149
Self::request(&t, &c, &s).map_err(mlua::Error::external)
5250
}
51+
52+
pub fn request(target: &str, configuration: &str, scheme: &str) -> mlua::Result<()> {
53+
Daemon::execute(&["build", target, configuration, scheme])
54+
}
5355
}

src/daemon/requests/drop.rs

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
#[cfg(feature = "mlua")]
2+
use crate::daemon::Daemon;
3+
4+
#[cfg(feature = "daemon")]
5+
use crate::daemon::{DaemonRequestHandler, DaemonState};
6+
7+
#[cfg(feature = "daemon")]
18
use anyhow::Result;
29

310
/// Drop a client
@@ -7,23 +14,14 @@ pub struct Drop {
714
pub root: String,
815
}
916

10-
#[cfg(feature = "daemon")]
11-
#[async_trait::async_trait]
12-
impl crate::daemon::DaemonRequestHandler for Drop {
13-
async fn handle(&self, state: crate::daemon::DaemonState) -> Result<()> {
14-
tracing::trace!("{:?}", self);
15-
state
16-
.lock()
17-
.await
18-
.remove_workspace(&self.root, self.pid)
19-
.await
20-
}
17+
impl Drop {
18+
pub const KEY: &'static str = "drop";
2119
}
2220

23-
impl TryFrom<Vec<&str>> for Drop {
24-
type Error = anyhow::Error;
25-
26-
fn try_from(args: Vec<&str>) -> Result<Self, Self::Error> {
21+
#[cfg(feature = "daemon")]
22+
#[async_trait::async_trait]
23+
impl DaemonRequestHandler<Drop> for Drop {
24+
fn parse(args: Vec<&str>) -> Result<Self> {
2725
if let (Some(pid), Some(root)) = (args.get(0), args.get(1)) {
2826
Ok(Self {
2927
pid: pid.parse::<i32>()?,
@@ -33,16 +31,23 @@ impl TryFrom<Vec<&str>> for Drop {
3331
anyhow::bail!("Missing arugments: {:?}", args)
3432
}
3533
}
34+
async fn handle(&self, state: DaemonState) -> Result<()> {
35+
tracing::trace!("{:?}", self);
36+
state
37+
.lock()
38+
.await
39+
.remove_workspace(&self.root, self.pid)
40+
.await
41+
}
3642
}
3743

44+
#[cfg(feature = "lua")]
3845
impl Drop {
39-
pub const KEY: &'static str = "drop";
40-
pub fn request(pid: i32, root: String) -> Result<()> {
41-
crate::daemon::Daemon::execute(&[Self::KEY, pid.to_string().as_str(), root.as_str()])
42-
}
43-
44-
#[cfg(feature = "lua")]
4546
pub fn lua(_: &mlua::Lua, (pid, root): (i32, String)) -> mlua::Result<()> {
4647
Self::request(pid, root).map_err(mlua::Error::external)
4748
}
49+
50+
pub fn request(pid: i32, root: String) -> mlua::Result<()> {
51+
Daemon::execute(&[Self::KEY, pid.to_string().as_str(), root.as_str()])
52+
}
4853
}

0 commit comments

Comments
 (0)