mirror of
https://github.com/OMGeeky/gdriver2.git
synced 2026-02-15 22:14:31 +01:00
misc
This commit is contained in:
14
Cargo.lock
generated
14
Cargo.lock
generated
@@ -421,8 +421,10 @@ dependencies = [
|
|||||||
"google-drive3",
|
"google-drive3",
|
||||||
"serde",
|
"serde",
|
||||||
"tarpc",
|
"tarpc",
|
||||||
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tracing",
|
"tracing",
|
||||||
|
"uuid",
|
||||||
"yup-oauth2",
|
"yup-oauth2",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1801,6 +1803,18 @@ version = "1.0.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
|
checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "uuid"
|
||||||
|
version = "1.20.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ee48d38b119b0cd71fe4141b30f5ba9c7c5d9f4e7a3a8b4a674e4b6ef789976f"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom 0.3.4",
|
||||||
|
"js-sys",
|
||||||
|
"serde_core",
|
||||||
|
"wasm-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "valuable"
|
name = "valuable"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
|
|||||||
@@ -14,8 +14,10 @@ tarpc.workspace = true
|
|||||||
futures.workspace = true
|
futures.workspace = true
|
||||||
chrono.workspace = true
|
chrono.workspace = true
|
||||||
google-drive3.workspace = true
|
google-drive3.workspace = true
|
||||||
|
uuid = { version = "1.7.0", features = ["v4", "serde"] }
|
||||||
|
|
||||||
yup-oauth2 = "12.1.2"
|
yup-oauth2 = "12.1.2"
|
||||||
|
thiserror = "2.0.18"
|
||||||
|
|
||||||
[dependencies.gdriver-common]
|
[dependencies.gdriver-common]
|
||||||
path = "../gdriver-common"
|
path = "../gdriver-common"
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
use futures::{future, prelude::*};
|
use futures::{future, prelude::*};
|
||||||
use std::net::SocketAddr;
|
|
||||||
use tarpc::{
|
use tarpc::{
|
||||||
context,
|
context,
|
||||||
server::{self, incoming::Incoming, Channel},
|
server::{self, incoming::Incoming, Channel},
|
||||||
tokio_serde::formats::Json,
|
tokio_serde::formats::Json,
|
||||||
};
|
};
|
||||||
|
use tokio::net::unix::SocketAddr;
|
||||||
|
|
||||||
mod prelude;
|
mod prelude;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ impl World for HelloServer {
|
|||||||
pub(super) async fn main() -> Result<()> {
|
pub(super) async fn main() -> Result<()> {
|
||||||
println!("Hello, world!");
|
println!("Hello, world!");
|
||||||
let config = &CONFIGURATION;
|
let config = &CONFIGURATION;
|
||||||
let server_addr = (config.ip, config.port);
|
let server_addr = (&config.socket_path);
|
||||||
let mut listener = tarpc::serde_transport::tcp::listen(&server_addr, Json::default).await?;
|
let mut listener = tarpc::serde_transport::unix::listen(&server_addr, Json::default).await?;
|
||||||
|
|
||||||
println!("Listening");
|
println!("Listening");
|
||||||
listener.config_mut().max_frame_length(usize::MAX);
|
listener.config_mut().max_frame_length(usize::MAX);
|
||||||
@@ -23,11 +23,21 @@ pub(super) async fn main() -> Result<()> {
|
|||||||
.filter_map(|r| future::ready(r.ok()))
|
.filter_map(|r| future::ready(r.ok()))
|
||||||
.map(server::BaseChannel::with_defaults)
|
.map(server::BaseChannel::with_defaults)
|
||||||
// Limit channels to 1 per IP.
|
// Limit channels to 1 per IP.
|
||||||
.max_channels_per_key(1, |t| t.transport().peer_addr().unwrap().ip())
|
.max_channels_per_key(1, |t| {
|
||||||
|
t.transport()
|
||||||
|
.peer_addr()
|
||||||
|
.unwrap()
|
||||||
|
.as_pathname()
|
||||||
|
.unwrap()
|
||||||
|
.to_str()
|
||||||
|
.unwrap()
|
||||||
|
.to_string()
|
||||||
|
})
|
||||||
// serve is generated by the service attribute. It takes as input any type implementing
|
// serve is generated by the service attribute. It takes as input any type implementing
|
||||||
// the generated World trait.
|
// the generated World trait.
|
||||||
.map(|channel| {
|
.map(|channel| {
|
||||||
let server = HelloServer(channel.transport().peer_addr().unwrap());
|
let c = channel.transport().peer_addr().unwrap();
|
||||||
|
let server = HelloServer(c);
|
||||||
channel.execute(server.serve()).for_each(spawn)
|
channel.execute(server.serve()).for_each(spawn)
|
||||||
})
|
})
|
||||||
// Max 10 channels.
|
// Max 10 channels.
|
||||||
|
|||||||
@@ -10,14 +10,17 @@ use tarpc::context::Context;
|
|||||||
use tokio::sync::Mutex;
|
use tokio::sync::Mutex;
|
||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
use crate::drive::Drive;
|
use crate::drive::Drive;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
use crate::service::sample_sym::spawn_twoway;
|
||||||
|
use tarpc::server::{BaseChannel, Channel};
|
||||||
|
|
||||||
use super::*;
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
struct GdriverServer {
|
struct GdriverServer {
|
||||||
socket_address: SocketAddr,
|
socket_address: SocketAddr,
|
||||||
drive: Arc<Mutex<Drive>>,
|
drive: Arc<Mutex<Drive>>,
|
||||||
|
client: GDriverClientClient,
|
||||||
}
|
}
|
||||||
impl GDriverService for GdriverServer {
|
impl GDriverService for GdriverServer {
|
||||||
async fn is_online(self, _: Context) -> bool {
|
async fn is_online(self, _: Context) -> bool {
|
||||||
@@ -168,8 +171,15 @@ impl GDriverService for GdriverServer {
|
|||||||
self,
|
self,
|
||||||
_: ::tarpc::context::Context,
|
_: ::tarpc::context::Context,
|
||||||
req: BackendActionRequest,
|
req: BackendActionRequest,
|
||||||
) -> std::result::Result<String, BackendActionError> {
|
) -> std::result::Result<AsyncResponse<String>, BackendActionError> {
|
||||||
println!("You are connected from {}", self.socket_address);
|
println!(
|
||||||
|
"You are connected from {}",
|
||||||
|
self.socket_address
|
||||||
|
.as_pathname()
|
||||||
|
.map(|p| p.to_str())
|
||||||
|
.flatten()
|
||||||
|
.unwrap_or("unknown")
|
||||||
|
);
|
||||||
|
|
||||||
match req {
|
match req {
|
||||||
BackendActionRequest::ShutdownGracefully => {
|
BackendActionRequest::ShutdownGracefully => {
|
||||||
@@ -182,21 +192,34 @@ impl GDriverService for GdriverServer {
|
|||||||
let drive = &self.drive;
|
let drive = &self.drive;
|
||||||
print_sample_tracking_state(drive).await;
|
print_sample_tracking_state(drive).await;
|
||||||
|
|
||||||
Ok(String::from("OK"))
|
Ok(AsyncResponse::Immediate(String::from("OK")))
|
||||||
}
|
}
|
||||||
BackendActionRequest::Ping => {
|
BackendActionRequest::Ping => {
|
||||||
println!("Ping request received");
|
println!("Ping request received");
|
||||||
Ok(String::from("Pong"))
|
Ok(AsyncResponse::Immediate(String::from("Pong")))
|
||||||
}
|
}
|
||||||
BackendActionRequest::RunLong => {
|
BackendActionRequest::RunLong => {
|
||||||
println!("RunLong request received");
|
println!("RunLong request received");
|
||||||
long_running_task(&self.drive).await;
|
long_running_task(&self.drive).await;
|
||||||
Ok(String::from("OK"))
|
Ok(AsyncResponse::Immediate(String::from("OK")))
|
||||||
}
|
}
|
||||||
BackendActionRequest::StartLong => {
|
BackendActionRequest::StartLong => {
|
||||||
println!("StartLong request received");
|
println!("StartLong request received");
|
||||||
tokio::spawn(async move { long_running_task(&self.drive).await });
|
let drive = self.drive.clone();
|
||||||
Ok(String::from("OK"))
|
let client = self.client.clone();
|
||||||
|
let task_id = TaskId(uuid::Uuid::new_v4().to_string());
|
||||||
|
let task_id_clone = task_id.clone();
|
||||||
|
tokio::spawn(async move {
|
||||||
|
long_running_task(&drive).await;
|
||||||
|
let _ = client
|
||||||
|
.report_task_result(
|
||||||
|
tarpc::context::current(),
|
||||||
|
task_id_clone,
|
||||||
|
TaskResult::Success("OK".to_string()),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
});
|
||||||
|
Ok(AsyncResponse::Pending(task_id))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -219,30 +242,121 @@ pub async fn start() -> Result<()> {
|
|||||||
let drive = Drive::new().await?;
|
let drive = Drive::new().await?;
|
||||||
let drive = Arc::new(Mutex::new(drive));
|
let drive = Arc::new(Mutex::new(drive));
|
||||||
|
|
||||||
let server_addr = (config.ip, config.port);
|
let mut listener =
|
||||||
let mut listener = tarpc::serde_transport::tcp::listen(&server_addr, Json::default).await?;
|
tarpc::serde_transport::unix::listen(&config.socket_path, Json::default).await?;
|
||||||
listener.config_mut().max_frame_length(usize::MAX);
|
listener.config_mut().max_frame_length(usize::MAX);
|
||||||
|
|
||||||
println!("Listening");
|
println!("Listening");
|
||||||
|
|
||||||
listener
|
listener
|
||||||
// Ignore accept errors.
|
// Ignore accept errors.
|
||||||
.filter_map(|r| future::ready(r.ok()))
|
.filter_map(|r| future::ready(r.ok()))
|
||||||
.map(server::BaseChannel::with_defaults)
|
.map(|transport| {
|
||||||
// // Limit channels to 1 per IP.
|
let peer_addr = transport.peer_addr().unwrap();
|
||||||
.max_channels_per_key(1, |t| t.transport().peer_addr().unwrap().ip())
|
let (server_channel, client_channel) = spawn_twoway(transport);
|
||||||
// serve is generated by the service attribute. It takes as input any type implementing
|
let client =
|
||||||
// the generated World trait.
|
GDriverClientClient::new(tarpc::client::Config::default(), client_channel).spawn();
|
||||||
.map(|channel| {
|
|
||||||
let c = channel.transport().peer_addr().unwrap();
|
|
||||||
let server = GdriverServer {
|
let server = GdriverServer {
|
||||||
socket_address: c,
|
socket_address: peer_addr,
|
||||||
drive: drive.clone(),
|
drive: drive.clone(),
|
||||||
|
client,
|
||||||
};
|
};
|
||||||
channel.execute(server.serve()).for_each(spawn)
|
BaseChannel::with_defaults(server_channel).execute(server.serve())
|
||||||
})
|
})
|
||||||
// Max 10 channels.
|
// Max 10 channels.
|
||||||
.buffer_unordered(10)
|
// .buffer_unordered(10)
|
||||||
.for_each(|_| async {})
|
.for_each(|_| async {})
|
||||||
.await;
|
.await;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mod sample_sym {
|
||||||
|
use futures::future::{AbortHandle, Abortable};
|
||||||
|
use futures::{Sink, TryFutureExt};
|
||||||
|
use futures::{SinkExt, Stream, StreamExt, TryStreamExt};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::io;
|
||||||
|
use tarpc::transport::channel::{ChannelError, UnboundedChannel};
|
||||||
|
use tracing::{debug, warn};
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub enum TwoWayMessage<Req, Resp> {
|
||||||
|
Request(tarpc::ClientMessage<Req>),
|
||||||
|
Response(tarpc::Response<Resp>),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(thiserror::Error, Debug)]
|
||||||
|
pub enum ChannelOrIoError {
|
||||||
|
#[error("{0}")]
|
||||||
|
ChannelError(#[from] ChannelError),
|
||||||
|
#[error("{0}")]
|
||||||
|
IoError(#[from] io::Error),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns two transports that multiplex over the given transport.
|
||||||
|
/// The first transport can be used by a server: it receives requests and sends back responses.
|
||||||
|
/// The second transport can be used by a client: it sends requests and receives back responses.
|
||||||
|
pub fn spawn_twoway<Req1, Resp1, Req2, Resp2, T>(
|
||||||
|
transport: T,
|
||||||
|
) -> (
|
||||||
|
UnboundedChannel<tarpc::ClientMessage<Req1>, tarpc::Response<Resp1>>,
|
||||||
|
UnboundedChannel<tarpc::Response<Resp2>, tarpc::ClientMessage<Req2>>,
|
||||||
|
)
|
||||||
|
where
|
||||||
|
T: Stream<Item = Result<TwoWayMessage<Req1, Resp2>, io::Error>>,
|
||||||
|
T: Sink<TwoWayMessage<Req2, Resp1>, Error = io::Error>,
|
||||||
|
T: Unpin + Send + 'static,
|
||||||
|
Req1: Send + 'static + Serialize + for<'de> Deserialize<'de>,
|
||||||
|
Resp1: Send + 'static + Serialize + for<'de> Deserialize<'de>,
|
||||||
|
Req2: Send + 'static + Serialize + for<'de> Deserialize<'de>,
|
||||||
|
Resp2: Send + 'static + Serialize + for<'de> Deserialize<'de>,
|
||||||
|
{
|
||||||
|
let (server, server_ret) = tarpc::transport::channel::unbounded();
|
||||||
|
let (client, client_ret) = tarpc::transport::channel::unbounded();
|
||||||
|
let (mut server_sink, server_stream) = server.split();
|
||||||
|
let (mut client_sink, client_stream) = client.split();
|
||||||
|
let (transport_sink, mut transport_stream) = transport.split();
|
||||||
|
|
||||||
|
let (abort_handle, abort_registration) = AbortHandle::new_pair();
|
||||||
|
|
||||||
|
// Task for inbound message handling
|
||||||
|
tokio::spawn(async move {
|
||||||
|
let e: Result<(), ChannelOrIoError> = async move {
|
||||||
|
while let Some(msg) = transport_stream.next().await {
|
||||||
|
match msg? {
|
||||||
|
TwoWayMessage::Request(req) => server_sink.send(req).await?,
|
||||||
|
TwoWayMessage::Response(resp) => client_sink.send(resp).await?,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
.await;
|
||||||
|
|
||||||
|
match e {
|
||||||
|
Ok(()) => debug!("transport_stream done"),
|
||||||
|
Err(e) => warn!("Error in inbound multiplexing: {}", e),
|
||||||
|
}
|
||||||
|
|
||||||
|
abort_handle.abort();
|
||||||
|
});
|
||||||
|
|
||||||
|
let abortable_sink_channel = Abortable::new(
|
||||||
|
futures::stream::select(
|
||||||
|
server_stream.map_ok(TwoWayMessage::Response),
|
||||||
|
client_stream.map_ok(TwoWayMessage::Request),
|
||||||
|
)
|
||||||
|
.map_err(ChannelOrIoError::ChannelError),
|
||||||
|
abort_registration,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Task for outbound message handling
|
||||||
|
tokio::spawn(
|
||||||
|
abortable_sink_channel
|
||||||
|
.forward(transport_sink.sink_map_err(ChannelOrIoError::IoError))
|
||||||
|
.inspect_ok(|_| debug!("transport_sink done"))
|
||||||
|
.inspect_err(|e| warn!("Error in outbound multiplexing: {}", e)),
|
||||||
|
);
|
||||||
|
|
||||||
|
(server_ret, client_ret)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use fuser::{mount2, MountOption};
|
use fuser::{mount2, spawn_mount2, MountOption};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::{error::Error, net::IpAddr, result::Result as StdResult};
|
use std::{error::Error, net::IpAddr, result::Result as StdResult};
|
||||||
|
|
||||||
@@ -18,13 +18,15 @@ async fn main() -> Result<()> {
|
|||||||
println!("Hello, world!");
|
println!("Hello, world!");
|
||||||
let config = &CONFIGURATION;
|
let config = &CONFIGURATION;
|
||||||
println!("Config: {:?}", **config);
|
println!("Config: {:?}", **config);
|
||||||
let client: GDriverServiceClient = create_client(config.ip, config.port).await?;
|
let (client, _handler) = create_client(&config.socket_path).await?;
|
||||||
let fs = DriveFilesystem::new(client);
|
|
||||||
let mountpoint = Path::new("/tmp/gdriver");
|
|
||||||
std::fs::create_dir_all(mountpoint)?;
|
|
||||||
mount2(fs, mountpoint, &[MountOption::RW, MountOption::AutoUnmount])?;
|
|
||||||
|
|
||||||
// service::start().await?;
|
// let fs = DriveFilesystem::new(client);
|
||||||
|
// let mountpoint = Path::new("/tmp/gdriver");
|
||||||
|
// std::fs::create_dir_all(mountpoint)?;
|
||||||
|
// // let mount_handle =
|
||||||
|
// mount2(fs, mountpoint, &[MountOption::RW, MountOption::AutoUnmount])?;
|
||||||
|
// mount_handle.guard.join().unwrap()?;
|
||||||
|
service::start_with_client(client, _handler).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
pub mod prelude;
|
pub mod prelude;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ pub async fn start() -> Result<()> {
|
|||||||
|
|
||||||
let name = "test1".to_string();
|
let name = "test1".to_string();
|
||||||
let config = &CONFIGURATION;
|
let config = &CONFIGURATION;
|
||||||
let client: WorldClient = create_client(config.ip, config.port).await?;
|
let client: WorldClient = create_client(&config.socket_path).await?;
|
||||||
|
|
||||||
let hello = client
|
let hello = client
|
||||||
.hello(tarpc::context::current(), name.to_string())
|
.hello(tarpc::context::current(), name.to_string())
|
||||||
@@ -18,14 +18,10 @@ pub async fn start() -> Result<()> {
|
|||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
pub async fn create_client(ip: IpAddr, port: u16) -> Result<WorldClient> {
|
pub async fn create_client(socket_path: impl AsRef<Path>) -> Result<WorldClient> {
|
||||||
let server_addr = (ip, port);
|
let transport = tarpc::serde_transport::unix::connect(socket_path, Json::default)
|
||||||
let transport = tarpc::serde_transport::tcp::connect(&server_addr, Json::default)
|
|
||||||
.await
|
.await
|
||||||
.map_err(|e| {
|
.inspect_err(|_| println!("Could not connect"))?;
|
||||||
println!("Could not connect");
|
|
||||||
e
|
|
||||||
})?;
|
|
||||||
let var_name = WorldClient::new(client::Config::default(), transport);
|
let var_name = WorldClient::new(client::Config::default(), transport);
|
||||||
let client = var_name.spawn();
|
let client = var_name.spawn();
|
||||||
Ok(client)
|
Ok(client)
|
||||||
|
|||||||
@@ -1,15 +1,46 @@
|
|||||||
use std::time;
|
use std::time;
|
||||||
|
|
||||||
use gdriver_common::ipc::gdriver_service::{BackendActionRequest, GDriverServiceClient};
|
use futures::prelude::*;
|
||||||
|
use gdriver_common::ipc::gdriver_service::{
|
||||||
|
AsyncResponse, BackendActionRequest, GDriverClient, GDriverServiceClient, TaskId, TaskResult,
|
||||||
|
};
|
||||||
|
use sample_sym::spawn_twoway;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
use tarpc::context::Context;
|
||||||
|
use tarpc::server::{BaseChannel, Channel};
|
||||||
|
use tokio::sync::mpsc;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub(crate) struct ClientHandler {
|
||||||
|
pending_tasks: Arc<Mutex<HashMap<String, mpsc::Sender<TaskResult>>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GDriverClient for ClientHandler {
|
||||||
|
async fn report_task_result(self, _: Context, id: TaskId, result: TaskResult) {
|
||||||
|
println!("Received task result for task {}: {:?}", id.0, result);
|
||||||
|
let mut tasks = self.pending_tasks.lock().unwrap();
|
||||||
|
if let Some(sender) = tasks.remove(&id.0) {
|
||||||
|
let _ = sender.send(result).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn start() -> Result<()> {
|
pub async fn start() -> Result<()> {
|
||||||
println!("Hello, world!");
|
println!("Hello, world!");
|
||||||
let config = &CONFIGURATION;
|
let config = &CONFIGURATION;
|
||||||
println!("Config: {:?}", **config);
|
println!("Config: {:?}", **config);
|
||||||
let client: GDriverServiceClient = create_client(config.ip, config.port).await?;
|
let (client, handler) = create_client(&config.socket_path).await?;
|
||||||
|
|
||||||
|
start_with_client(client, handler).await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) async fn start_with_client(
|
||||||
|
client: GDriverServiceClient,
|
||||||
|
handler: ClientHandler,
|
||||||
|
) -> Result<()> {
|
||||||
let hello = client
|
let hello = client
|
||||||
.do_something2(tarpc::context::current(), BackendActionRequest::Ping)
|
.do_something2(tarpc::context::current(), BackendActionRequest::Ping)
|
||||||
.await;
|
.await;
|
||||||
@@ -42,20 +73,150 @@ pub async fn start() -> Result<()> {
|
|||||||
.as_secs();
|
.as_secs();
|
||||||
|
|
||||||
match hello {
|
match hello {
|
||||||
Ok(hello) => println!("Start Long returned after {} seconds: {:?}", seconds, hello),
|
Ok(Ok(AsyncResponse::Pending(task_id))) => {
|
||||||
Err(e) => println!(":( {:?}", (e)),
|
println!("Start Long returned pending task: {:?}", task_id);
|
||||||
|
let (tx, mut rx) = mpsc::channel(1);
|
||||||
|
handler
|
||||||
|
.pending_tasks
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.insert(task_id.0.clone(), tx);
|
||||||
|
|
||||||
|
if let Some(result) = rx.recv().await {
|
||||||
|
println!(
|
||||||
|
"Received async result after {} seconds: {:?}",
|
||||||
|
(time::SystemTime::now().duration_since(start))
|
||||||
|
.unwrap()
|
||||||
|
.as_secs(),
|
||||||
|
result
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(Ok(AsyncResponse::Immediate(res))) => {
|
||||||
|
println!("Start Long returned immediate: {:?}", res)
|
||||||
|
}
|
||||||
|
Ok(Err(e)) => println!("Backend Error: {:?}", e),
|
||||||
|
Err(e) => println!("RPC Error: {:?}", e),
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
pub async fn create_client(ip: IpAddr, port: u16) -> Result<GDriverServiceClient> {
|
|
||||||
let server_addr = (ip, port);
|
pub async fn create_client(
|
||||||
let transport = tarpc::serde_transport::tcp::connect(&server_addr, Json::default)
|
socket_path: impl AsRef<Path>,
|
||||||
|
) -> Result<(GDriverServiceClient, ClientHandler)> {
|
||||||
|
let transport = tarpc::serde_transport::unix::connect(socket_path, Json::default)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
println!("Could not connect");
|
println!("Could not connect");
|
||||||
e
|
e
|
||||||
})?;
|
})?;
|
||||||
let service = GDriverServiceClient::new(client::Config::default(), transport);
|
|
||||||
let client = service.spawn();
|
let (client_channel, server_channel) = spawn_twoway(transport);
|
||||||
Ok(client)
|
|
||||||
|
let client = GDriverServiceClient::new(client::Config::default(), server_channel).spawn();
|
||||||
|
|
||||||
|
let handler = ClientHandler {
|
||||||
|
pending_tasks: Arc::new(Mutex::new(HashMap::new())),
|
||||||
|
};
|
||||||
|
|
||||||
|
let handler_clone = handler.clone();
|
||||||
|
tokio::spawn(async move {
|
||||||
|
BaseChannel::with_defaults(client_channel)
|
||||||
|
.execute(handler_clone.serve())
|
||||||
|
.for_each(|_| async {})
|
||||||
|
.await;
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok((client, handler))
|
||||||
|
}
|
||||||
|
|
||||||
|
mod sample_sym {
|
||||||
|
use futures::future::{AbortHandle, Abortable};
|
||||||
|
use futures::{Sink, TryFutureExt};
|
||||||
|
use futures::{SinkExt, Stream, StreamExt, TryStreamExt};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::io;
|
||||||
|
use tarpc::transport::channel::{ChannelError, UnboundedChannel};
|
||||||
|
use tracing::{debug, warn};
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub enum TwoWayMessage<Req, Resp> {
|
||||||
|
Request(tarpc::ClientMessage<Req>),
|
||||||
|
Response(tarpc::Response<Resp>),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(thiserror::Error, Debug)]
|
||||||
|
pub enum ChannelOrIoError {
|
||||||
|
#[error("{0}")]
|
||||||
|
ChannelError(#[from] ChannelError),
|
||||||
|
#[error("{0}")]
|
||||||
|
IoError(#[from] io::Error),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns two transports that multiplex over the given transport.
|
||||||
|
/// The first transport can be used by a server: it receives requests and sends back responses.
|
||||||
|
/// The second transport can be used by a client: it sends requests and receives back responses.
|
||||||
|
pub fn spawn_twoway<Req1, Resp1, Req2, Resp2, T>(
|
||||||
|
transport: T,
|
||||||
|
) -> (
|
||||||
|
UnboundedChannel<tarpc::ClientMessage<Req1>, tarpc::Response<Resp1>>,
|
||||||
|
UnboundedChannel<tarpc::Response<Resp2>, tarpc::ClientMessage<Req2>>,
|
||||||
|
)
|
||||||
|
where
|
||||||
|
T: Stream<Item = Result<TwoWayMessage<Req1, Resp2>, io::Error>>,
|
||||||
|
T: Sink<TwoWayMessage<Req2, Resp1>, Error = io::Error>,
|
||||||
|
T: Unpin + Send + 'static,
|
||||||
|
Req1: Send + 'static + Serialize + for<'de> Deserialize<'de>,
|
||||||
|
Resp1: Send + 'static + Serialize + for<'de> Deserialize<'de>,
|
||||||
|
Req2: Send + 'static + Serialize + for<'de> Deserialize<'de>,
|
||||||
|
Resp2: Send + 'static + Serialize + for<'de> Deserialize<'de>,
|
||||||
|
{
|
||||||
|
let (server, server_ret) = tarpc::transport::channel::unbounded();
|
||||||
|
let (client, client_ret) = tarpc::transport::channel::unbounded();
|
||||||
|
let (mut server_sink, server_stream) = server.split();
|
||||||
|
let (mut client_sink, client_stream) = client.split();
|
||||||
|
let (transport_sink, mut transport_stream) = transport.split();
|
||||||
|
|
||||||
|
let (abort_handle, abort_registration) = AbortHandle::new_pair();
|
||||||
|
|
||||||
|
// Task for inbound message handling
|
||||||
|
tokio::spawn(async move {
|
||||||
|
let e: Result<(), ChannelOrIoError> = async move {
|
||||||
|
while let Some(msg) = transport_stream.next().await {
|
||||||
|
match msg? {
|
||||||
|
TwoWayMessage::Request(req) => server_sink.send(req).await?,
|
||||||
|
TwoWayMessage::Response(resp) => client_sink.send(resp).await?,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
.await;
|
||||||
|
|
||||||
|
match e {
|
||||||
|
Ok(()) => debug!("transport_stream done"),
|
||||||
|
Err(e) => warn!("Error in inbound multiplexing: {}", e),
|
||||||
|
}
|
||||||
|
|
||||||
|
abort_handle.abort();
|
||||||
|
});
|
||||||
|
|
||||||
|
let abortable_sink_channel = Abortable::new(
|
||||||
|
futures::stream::select(
|
||||||
|
server_stream.map_ok(TwoWayMessage::Response),
|
||||||
|
client_stream.map_ok(TwoWayMessage::Request),
|
||||||
|
)
|
||||||
|
.map_err(ChannelOrIoError::ChannelError),
|
||||||
|
abort_registration,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Task for outbound message handling
|
||||||
|
tokio::spawn(
|
||||||
|
abortable_sink_channel
|
||||||
|
.forward(transport_sink.sink_map_err(ChannelOrIoError::IoError))
|
||||||
|
.inspect_ok(|_| debug!("transport_sink done"))
|
||||||
|
.inspect_err(|e| warn!("Error in outbound multiplexing: {}", e)),
|
||||||
|
);
|
||||||
|
|
||||||
|
(server_ret, client_ret)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,10 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use confique::{Config, Layer};
|
use confique::{Config, Layer};
|
||||||
use std::net::{IpAddr, Ipv6Addr};
|
|
||||||
const IP_DEFAULT: IpAddr = IpAddr::V6(Ipv6Addr::LOCALHOST);
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Config, Clone)]
|
#[derive(Debug, Serialize, Deserialize, Config, Clone)]
|
||||||
pub struct Configuration {
|
pub struct Configuration {
|
||||||
#[config(default = 33333)]
|
#[config(default = "\0gdriver2_v3.sock")]
|
||||||
pub port: u16,
|
pub socket_path: String,
|
||||||
// #[config(default = Test)]
|
|
||||||
pub ip: std::net::IpAddr,
|
|
||||||
}
|
}
|
||||||
pub fn load_config() -> Result<Configuration> {
|
pub fn load_config() -> Result<Configuration> {
|
||||||
Ok(add_default_locations(Config::builder()).load()?)
|
Ok(add_default_locations(Config::builder()).load()?)
|
||||||
@@ -19,12 +15,7 @@ pub fn load_config_with_path(path: &Path) -> Result<Configuration> {
|
|||||||
fn add_default_locations(
|
fn add_default_locations(
|
||||||
builder: confique::Builder<Configuration>,
|
builder: confique::Builder<Configuration>,
|
||||||
) -> confique::Builder<Configuration> {
|
) -> confique::Builder<Configuration> {
|
||||||
type P = <Configuration as Config>::Layer;
|
builder.env().file("config.toml")
|
||||||
let prebuilt = P {
|
|
||||||
ip: Some(IP_DEFAULT),
|
|
||||||
..P::empty()
|
|
||||||
};
|
|
||||||
builder.env().file("config.toml").preloaded(prebuilt)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
|
|||||||
@@ -29,8 +29,29 @@ pub trait GDriverService {
|
|||||||
/// Returns true if the file was had remote changes and was updated
|
/// Returns true if the file was had remote changes and was updated
|
||||||
async fn update_changes_for_file(id: DriveId) -> StdResult<bool, UpdateChangesError>;
|
async fn update_changes_for_file(id: DriveId) -> StdResult<bool, UpdateChangesError>;
|
||||||
async fn update_changes() -> StdResult<(), UpdateChangesError>;
|
async fn update_changes() -> StdResult<(), UpdateChangesError>;
|
||||||
async fn do_something2(req: BackendActionRequest) -> StdResult<String, BackendActionError>;
|
async fn do_something2(req: BackendActionRequest) -> StdResult<AsyncResponse<String>, BackendActionError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tarpc::service]
|
||||||
|
pub trait GDriverClient {
|
||||||
|
async fn report_task_result(id: TaskId, result: TaskResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
|
pub struct TaskId(pub String);
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub enum AsyncResponse<T> {
|
||||||
|
Immediate(T),
|
||||||
|
Pending(TaskId),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub enum TaskResult {
|
||||||
|
Success(String),
|
||||||
|
Error(String),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub enum BackendActionRequest {
|
pub enum BackendActionRequest {
|
||||||
ShutdownGracefully,
|
ShutdownGracefully,
|
||||||
|
|||||||
Reference in New Issue
Block a user