|
1 | 1 | use log::Level; |
| 2 | +use std::path::PathBuf; |
2 | 3 | use tap::Pipe; |
3 | 4 | use tokio::fs::{metadata, read_to_string, remove_file, write}; |
4 | | -use tokio::io::AsyncReadExt; |
5 | 5 | use tokio::net::UnixListener; |
6 | 6 | use xbase::util::pid; |
7 | | -use xbase::Result; |
8 | 7 | use xbase::{constants::*, RequestHandler}; |
9 | | -use xbase_proto::{Message, Request}; |
| 8 | +use xbase_proto::*; |
10 | 9 |
|
| 10 | +#[derive(Clone)] |
| 11 | +struct Server; |
| 12 | + |
| 13 | +#[tarpc::server] |
| 14 | +impl xbase_proto::XBase for Server { |
| 15 | + /// Register project root with a path to setup logs |
| 16 | + async fn register(self, _: Context, req: RegisterRequest) -> Result<PathBuf> { |
| 17 | + req.handle().await?; |
| 18 | + Ok("/bin/cp".into()) |
| 19 | + } |
| 20 | + /// Build Project and get path to where to build log will be located |
| 21 | + async fn build(self, _: Context, req: BuildRequest) -> Result<PathBuf> { |
| 22 | + // NOTE: Required because of nvim-rs |
| 23 | + tokio::spawn(async { req.handle().await }); |
| 24 | + Ok(PathBuf::default()) |
| 25 | + } |
| 26 | + /// Run Project and get path to where to Runtime log will be located |
| 27 | + async fn run(self, _: Context, req: RunRequest) -> Result<PathBuf> { |
| 28 | + // NOTE: Required because of nvim-rs |
| 29 | + tokio::spawn(async { req.handle().await }); |
| 30 | + Ok(PathBuf::default()) |
| 31 | + } |
| 32 | + /// Drop project root |
| 33 | + async fn drop(self, _: Context, req: DropRequest) -> Result<()> { |
| 34 | + // NOTE: Required because of nvim-rs |
| 35 | + tokio::spawn(async { req.handle().await }); |
| 36 | + Ok(()) |
| 37 | + } |
| 38 | +} |
11 | 39 | #[tokio::main] |
12 | | -async fn main() -> Result<()> { |
| 40 | +async fn main() -> std::result::Result<(), Box<dyn std::error::Error>> { |
13 | 41 | ensure_single_instance().await?; |
14 | 42 |
|
15 | 43 | let listener = UnixListener::bind(DAEMON_SOCKET_PATH).unwrap(); |
16 | | - |
| 44 | + let codec_builder = LengthDelimitedCodec::builder(); |
17 | 45 | log::setup("/tmp", "xbase-daemon.log", Level::DEBUG, true)?; |
18 | | - |
19 | 46 | log::info!("Started"); |
20 | 47 |
|
21 | 48 | loop { |
22 | | - if let Ok((mut s, _)) = listener.accept().await { |
| 49 | + if let Ok((s, _)) = listener.accept().await { |
23 | 50 | tokio::spawn(async move { |
24 | | - let msg = { |
25 | | - let mut msg = String::default(); |
26 | | - if let Err(e) = s.read_to_string(&mut msg).await { |
27 | | - return log::error!("[Read Error]: {:?}", e); |
28 | | - }; |
29 | | - msg |
30 | | - }; |
31 | | - |
32 | | - if msg.is_empty() { |
33 | | - return; |
34 | | - } |
35 | | - |
36 | | - let req = match Request::read(msg.clone()) { |
37 | | - Err(e) => { |
38 | | - return log::error!("[Parse Error]: {:?} message: {msg}", e); |
39 | | - } |
40 | | - Ok(req) => req, |
41 | | - }; |
42 | | - |
43 | | - if let Err(e) = handle(req).await { |
44 | | - return log::error!("[Failure]: Cause: ({:?})", e); |
45 | | - }; |
| 51 | + let framed = codec_builder.new_framed(s); |
| 52 | + let transport = transport::new(framed, Json::default()); |
| 53 | + BaseChannel::with_defaults(transport) |
| 54 | + .execute(Server.serve()) |
| 55 | + .await; |
46 | 56 |
|
47 | 57 | let state = DAEMON_STATE.clone(); |
48 | 58 | let mut state = state.lock().await; |
49 | 59 | state.validate().await; |
50 | | - |
51 | | - // update_watchers(state.clone()).await; |
52 | 60 | }); |
53 | 61 | } else { |
54 | 62 | log::error!("Fail to accept a connection") |
55 | 63 | }; |
56 | 64 | } |
57 | 65 | } |
58 | 66 |
|
59 | | -async fn handle(req: Request) -> Result<()> { |
60 | | - match req.message { |
61 | | - Message::Build(c) => RequestHandler::handle(c).await, |
62 | | - Message::Run(c) => RequestHandler::handle(c).await, |
63 | | - Message::Register(c) => RequestHandler::handle(c).await, |
64 | | - Message::Drop(c) => RequestHandler::handle(c).await, |
65 | | - } |
66 | | -} |
67 | | - |
68 | 67 | async fn ensure_single_instance() -> Result<()> { |
69 | 68 | if metadata(DAEMON_SOCKET_PATH).await.ok().is_some() { |
70 | 69 | remove_file(DAEMON_SOCKET_PATH).await.ok(); |
|
0 commit comments