mirror of
https://github.com/hexedtech/codemp.git
synced 2024-11-22 15:24:48 +01:00
chore: proto cleanup and simplification
reuse as much as possible, keep rpc messages close with their rpc, helper struct for uuid with into() and from(). also replaced the simple things, such as imports and struct fields
This commit is contained in:
parent
3738f7beb4
commit
1cf17dc151
14 changed files with 135 additions and 131 deletions
8
build.rs
8
build.rs
|
@ -5,14 +5,12 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
// .build_transport(cfg!(feature = "transport"))
|
// .build_transport(cfg!(feature = "transport"))
|
||||||
.compile(
|
.compile(
|
||||||
&[
|
&[
|
||||||
"proto/user.proto",
|
"proto/common.proto",
|
||||||
"proto/cursor.proto",
|
"proto/cursor.proto",
|
||||||
"proto/files.proto",
|
"proto/files.proto",
|
||||||
|
"proto/auth.proto",
|
||||||
"proto/workspace.proto",
|
"proto/workspace.proto",
|
||||||
"proto/buffer_service.proto",
|
"proto/buffer.proto",
|
||||||
"proto/cursor_service.proto",
|
|
||||||
"proto/workspace_service.proto",
|
|
||||||
"proto/auth_service.proto",
|
|
||||||
],
|
],
|
||||||
&["proto"],
|
&["proto"],
|
||||||
)?;
|
)?;
|
||||||
|
|
|
@ -2,21 +2,19 @@ syntax = "proto2";
|
||||||
|
|
||||||
package auth;
|
package auth;
|
||||||
|
|
||||||
|
|
||||||
// authenticates users, issuing tokens
|
// authenticates users, issuing tokens
|
||||||
service Auth {
|
service Auth {
|
||||||
// send credentials and join a workspace
|
// send credentials and join a workspace, returns ready to use token
|
||||||
rpc Login (WorkspaceJoinRequest) returns (Token);
|
rpc Login (WorkspaceJoinRequest) returns (Token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
message Token {
|
message Token {
|
||||||
required string token = 1;
|
required string token = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO one-request-to-do-it-all from login to workspace access
|
||||||
message WorkspaceJoinRequest {
|
message WorkspaceJoinRequest {
|
||||||
required string workspace_id = 1;
|
required string username = 1;
|
||||||
required string username = 2;
|
required string password = 2;
|
||||||
required string password = 3;
|
optional string workspace_id = 3;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,20 @@
|
||||||
syntax = "proto2";
|
syntax = "proto2";
|
||||||
|
|
||||||
|
import "common.proto";
|
||||||
|
|
||||||
package buffer;
|
package buffer;
|
||||||
|
|
||||||
// handle buffer changes, keep in sync users
|
// handle buffer changes, keep in sync users
|
||||||
service Buffer {
|
service Buffer {
|
||||||
// attach to a buffer and receive operations
|
// attach to a buffer and receive operations
|
||||||
rpc Attach (stream Operation) returns (stream Operation);
|
rpc Attach (stream Operation) returns (stream BufferEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
message Operation {
|
message Operation {
|
||||||
required bytes data = 1;
|
required bytes data = 1;
|
||||||
optional string user = 2;
|
}
|
||||||
optional string path = 3;
|
|
||||||
}
|
message BufferEvent {
|
||||||
|
required Operation op = 1;
|
||||||
|
required common.Identity user = 2;
|
||||||
|
}
|
||||||
|
|
|
@ -3,16 +3,16 @@ syntax = "proto2";
|
||||||
package common;
|
package common;
|
||||||
|
|
||||||
|
|
||||||
// payload identifying user
|
// a wrapper payload representing an uuid
|
||||||
message UserIdentity {
|
message Identity {
|
||||||
// user identifier
|
// uuid bytes, as string
|
||||||
required string id = 1;
|
required string id = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message UserList {
|
// a collection of identities
|
||||||
repeated UserIdentity users = 1;
|
message IdentityList {
|
||||||
|
repeated Identity users = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message Empty{
|
//generic Empty message
|
||||||
//generic Empty message
|
message Empty { }
|
||||||
}
|
|
||||||
|
|
|
@ -2,17 +2,15 @@ syntax = "proto2";
|
||||||
|
|
||||||
package cursor;
|
package cursor;
|
||||||
import "common.proto";
|
import "common.proto";
|
||||||
|
import "files.proto";
|
||||||
|
|
||||||
// handle cursor events and broadcast to all users
|
// handle cursor events and broadcast to all users
|
||||||
service Cursor {
|
service Cursor {
|
||||||
// subscribe to a workspace's cursor events
|
// subscribe to a workspace's cursor events
|
||||||
rpc Attach (stream cursor.CursorEvent) returns (stream cursor.CursorEvent);
|
rpc Attach (stream cursor.CursorPosition) returns (stream cursor.CursorEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// empty request
|
|
||||||
message MovedResponse {}
|
|
||||||
|
|
||||||
// a tuple indicating row and column
|
// a tuple indicating row and column
|
||||||
message RowCol {
|
message RowCol {
|
||||||
required int32 row = 1;
|
required int32 row = 1;
|
||||||
|
@ -22,7 +20,7 @@ message RowCol {
|
||||||
// cursor position object
|
// cursor position object
|
||||||
message CursorPosition {
|
message CursorPosition {
|
||||||
// path of current buffer this cursor is into
|
// path of current buffer this cursor is into
|
||||||
required string buffer = 1;
|
required files.BufferNode buffer = 1;
|
||||||
// cursor start position
|
// cursor start position
|
||||||
required RowCol start = 2;
|
required RowCol start = 2;
|
||||||
// cursor end position
|
// cursor end position
|
||||||
|
@ -32,7 +30,7 @@ message CursorPosition {
|
||||||
// cursor event, with user id and cursor position
|
// cursor event, with user id and cursor position
|
||||||
message CursorEvent {
|
message CursorEvent {
|
||||||
// user moving the cursor
|
// user moving the cursor
|
||||||
required common.UserIdentity user = 1;
|
required common.Identity user = 1;
|
||||||
// new cursor position
|
// new cursor position
|
||||||
required CursorPosition position = 2;
|
required CursorPosition position = 2;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,8 +9,3 @@ message BufferNode {
|
||||||
message BufferTree {
|
message BufferTree {
|
||||||
repeated BufferNode buffers = 1;
|
repeated BufferNode buffers = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message WorkspaceFileTree {
|
|
||||||
// list of strings may be more efficient but it's a lot more hassle
|
|
||||||
required string payload = 1; // spappolata di json
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
syntax = "proto2";
|
|
||||||
|
|
||||||
package user;
|
|
||||||
|
|
||||||
|
|
||||||
// payload identifying user
|
|
||||||
message UserIdentity {
|
|
||||||
// user identifier
|
|
||||||
required string id = 1;
|
|
||||||
}
|
|
|
@ -1,29 +1,29 @@
|
||||||
syntax = "proto2";
|
syntax = "proto2";
|
||||||
|
|
||||||
package workspace;
|
package workspace;
|
||||||
|
|
||||||
|
import "common.proto";
|
||||||
import "files.proto";
|
import "files.proto";
|
||||||
import "auth.proto";
|
import "auth.proto";
|
||||||
import "common.proto";
|
|
||||||
|
|
||||||
service Workspace {
|
service Workspace {
|
||||||
rpc CreateWorkspace (workspace.WorkspaceId) returns (common.Empty);
|
rpc Attach (common.Empty) returns (stream WorkspaceEvent);
|
||||||
|
|
||||||
rpc RequestAccess (workspace.BufferPath) returns (auth.Token);
|
rpc CreateBuffer (files.BufferNode) returns (common.Empty);
|
||||||
rpc LeaveWorkspace (workspace.WorkspaceId) returns (common.Empty);
|
rpc AccessBuffer (files.BufferNode) returns (BufferCredentials);
|
||||||
rpc CreateBuffer (workspace.BufferPath) returns (common.Empty);
|
rpc DeleteBuffer (files.BufferNode) returns (common.Empty);
|
||||||
|
|
||||||
rpc ListBuffers (common.Empty) returns (files.BufferTree);
|
rpc ListBuffers (common.Empty) returns (files.BufferTree);
|
||||||
rpc ListUsers (common.Empty) returns (common.UserList);
|
rpc ListUsers (common.Empty) returns (common.IdentityList);
|
||||||
rpc ListBufferUsers (workspace.BufferPath) returns (common.UserList); //TODO discuss
|
rpc ListBufferUsers (files.BufferNode) returns (common.IdentityList); //TODO discuss
|
||||||
rpc Attach (common.Empty) returns (stream workspace.WorkspaceEvent);
|
|
||||||
rpc Delete (workspace.BufferPath) returns (common.Empty); //deletes buffer
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message WorkspaceEvent {
|
message WorkspaceEvent {
|
||||||
message UserJoin {
|
message UserJoin {
|
||||||
required common.UserIdentity id = 1;
|
required common.Identity user = 1;
|
||||||
}
|
}
|
||||||
message UserLeave {
|
message UserLeave {
|
||||||
required common.UserIdentity id = 1;
|
required common.Identity user = 1;
|
||||||
}
|
}
|
||||||
message FileCreate {
|
message FileCreate {
|
||||||
required string path = 1;
|
required string path = 1;
|
||||||
|
@ -45,12 +45,7 @@ message WorkspaceEvent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
message BufferPath {
|
message BufferCredentials {
|
||||||
// buffer path to operate onto
|
required common.Identity id = 1;
|
||||||
required string path = 1;
|
required auth.Token token = 2;
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
message WorkspaceId {
|
|
||||||
required string id = 1;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ use woot::woot::Woot;
|
||||||
use crate::errors::IgnorableError;
|
use crate::errors::IgnorableError;
|
||||||
use crate::api::controller::ControllerWorker;
|
use crate::api::controller::ControllerWorker;
|
||||||
use crate::api::TextChange;
|
use crate::api::TextChange;
|
||||||
use crate::proto::buffer_service::Operation;
|
use crate::proto::buffer::{BufferEvent, Operation};
|
||||||
|
|
||||||
use super::controller::BufferController;
|
use super::controller::BufferController;
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ impl BufferWorker {
|
||||||
impl ControllerWorker<TextChange> for BufferWorker {
|
impl ControllerWorker<TextChange> for BufferWorker {
|
||||||
type Controller = BufferController;
|
type Controller = BufferController;
|
||||||
type Tx = mpsc::Sender<Operation>;
|
type Tx = mpsc::Sender<Operation>;
|
||||||
type Rx = Streaming<Operation>;
|
type Rx = Streaming<BufferEvent>;
|
||||||
|
|
||||||
fn subscribe(&self) -> BufferController {
|
fn subscribe(&self) -> BufferController {
|
||||||
BufferController::new(
|
BufferController::new(
|
||||||
|
@ -130,8 +130,6 @@ impl ControllerWorker<TextChange> for BufferWorker {
|
||||||
for op in ops {
|
for op in ops {
|
||||||
let operation = Operation {
|
let operation = Operation {
|
||||||
data: postcard::to_extend(&op, Vec::new()).unwrap(),
|
data: postcard::to_extend(&op, Vec::new()).unwrap(),
|
||||||
user: None,
|
|
||||||
path: Some(self.name.clone())
|
|
||||||
};
|
};
|
||||||
|
|
||||||
match tx.send(operation).await {
|
match tx.send(operation).await {
|
||||||
|
@ -151,8 +149,8 @@ impl ControllerWorker<TextChange> for BufferWorker {
|
||||||
res = rx.message() => match res {
|
res = rx.message() => match res {
|
||||||
Err(_e) => break,
|
Err(_e) => break,
|
||||||
Ok(None) => break,
|
Ok(None) => break,
|
||||||
Ok(Some(change)) => match postcard::from_bytes::<Op>(&change.data) {
|
Ok(Some(change)) => match postcard::from_bytes::<Op>(&change.op.data) {
|
||||||
Ok(op) => {
|
Ok(op) => { // TODO here in change we receive info about the author, maybe propagate?
|
||||||
self.buffer.merge(op);
|
self.buffer.merge(op);
|
||||||
self.content.send(self.buffer.view()).unwrap_or_warn("could not send buffer update");
|
self.content.send(self.buffer.view()).unwrap_or_warn("could not send buffer update");
|
||||||
for tx in self.pollers.drain(..) {
|
for tx in self.pollers.drain(..) {
|
||||||
|
|
|
@ -11,13 +11,19 @@ use tonic::service::Interceptor;
|
||||||
use tonic::transport::{Channel, Endpoint};
|
use tonic::transport::{Channel, Endpoint};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::api::controller::ControllerWorker;
|
use crate::proto::auth::auth_client::AuthClient;
|
||||||
use crate::cursor::worker::CursorWorker;
|
use crate::{
|
||||||
use crate::proto::buffer_service::buffer_client::BufferClient;
|
api::controller::ControllerWorker,
|
||||||
use crate::proto::cursor_service::cursor_client::CursorClient;
|
cursor::worker::CursorWorker,
|
||||||
use crate::proto::workspace::{JoinRequest, Token, WorkspaceDetails};
|
proto::{
|
||||||
use crate::proto::workspace_service::workspace_client::WorkspaceClient;
|
common::Empty,
|
||||||
use crate::workspace::Workspace;
|
buffer::buffer_client::BufferClient,
|
||||||
|
cursor::cursor_client::CursorClient,
|
||||||
|
auth::{Token, WorkspaceJoinRequest},
|
||||||
|
workspace::workspace_client::WorkspaceClient,
|
||||||
|
},
|
||||||
|
workspace::Workspace
|
||||||
|
};
|
||||||
|
|
||||||
/// codemp client manager
|
/// codemp client manager
|
||||||
///
|
///
|
||||||
|
@ -49,9 +55,10 @@ impl Interceptor for ClientInterceptor {
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub(crate) struct Services {
|
pub(crate) struct Services {
|
||||||
pub(crate) workspace: crate::proto::workspace_service::workspace_client::WorkspaceClient<InterceptedService<Channel, ClientInterceptor>>,
|
pub(crate) workspace: WorkspaceClient<InterceptedService<Channel, ClientInterceptor>>,
|
||||||
pub(crate) buffer: crate::proto::buffer_service::buffer_client::BufferClient<InterceptedService<Channel, ClientInterceptor>>,
|
pub(crate) buffer: BufferClient<InterceptedService<Channel, ClientInterceptor>>,
|
||||||
pub(crate) cursor: crate::proto::cursor_service::cursor_client::CursorClient<InterceptedService<Channel, ClientInterceptor>>,
|
pub(crate) cursor: CursorClient<InterceptedService<Channel, ClientInterceptor>>,
|
||||||
|
pub(crate) auth: AuthClient<Channel>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO meno losco
|
// TODO meno losco
|
||||||
|
@ -90,14 +97,13 @@ impl Client {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// creates a new workspace (and joins it implicitly), returns an [tokio::sync::RwLock] to interact with it
|
pub async fn login(&self, username: String, password: String, workspace_id: Option<String>) -> crate::Result<()> {
|
||||||
pub async fn create_workspace(&mut self, workspace_id: &str) -> crate::Result<Arc<RwLock<Workspace>>> {
|
Ok(self.token_tx.send(
|
||||||
let mut workspace_client = self.services.workspace.clone();
|
self.services.auth.clone()
|
||||||
workspace_client.create_workspace(
|
.login(WorkspaceJoinRequest { username, password, workspace_id})
|
||||||
tonic::Request::new(WorkspaceDetails { id: workspace_id.to_string() })
|
.await?
|
||||||
).await?;
|
.into_inner()
|
||||||
|
)?)
|
||||||
self.join_workspace(workspace_id).await
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// join a workspace, returns an [tokio::sync::RwLock] to interact with it
|
/// join a workspace, returns an [tokio::sync::RwLock] to interact with it
|
||||||
|
|
|
@ -6,7 +6,7 @@ use tokio::sync::{mpsc, broadcast::{self, error::{TryRecvError, RecvError}}, Mut
|
||||||
use tonic::async_trait;
|
use tonic::async_trait;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::{api::Controller, errors::IgnorableError, proto::{cursor::{CursorEvent, CursorPosition}, user::UserIdentity}};
|
use crate::{api::Controller, errors::IgnorableError, proto::cursor::{CursorEvent, CursorPosition}};
|
||||||
|
|
||||||
/// the cursor controller implementation
|
/// the cursor controller implementation
|
||||||
///
|
///
|
||||||
|
@ -22,7 +22,7 @@ use crate::{api::Controller, errors::IgnorableError, proto::{cursor::{CursorEven
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct CursorController {
|
pub struct CursorController {
|
||||||
user_id: Uuid,
|
user_id: Uuid,
|
||||||
op: mpsc::UnboundedSender<CursorEvent>,
|
op: mpsc::UnboundedSender<CursorPosition>,
|
||||||
last_op: Mutex<watch::Receiver<CursorEvent>>,
|
last_op: Mutex<watch::Receiver<CursorEvent>>,
|
||||||
stream: Mutex<broadcast::Receiver<CursorEvent>>,
|
stream: Mutex<broadcast::Receiver<CursorEvent>>,
|
||||||
stop: mpsc::UnboundedSender<()>,
|
stop: mpsc::UnboundedSender<()>,
|
||||||
|
@ -37,7 +37,7 @@ impl Drop for CursorController {
|
||||||
impl CursorController {
|
impl CursorController {
|
||||||
pub(crate) fn new(
|
pub(crate) fn new(
|
||||||
user_id: Uuid,
|
user_id: Uuid,
|
||||||
op: mpsc::UnboundedSender<CursorEvent>,
|
op: mpsc::UnboundedSender<CursorPosition>,
|
||||||
last_op: Mutex<watch::Receiver<CursorEvent>>,
|
last_op: Mutex<watch::Receiver<CursorEvent>>,
|
||||||
stream: Mutex<broadcast::Receiver<CursorEvent>>,
|
stream: Mutex<broadcast::Receiver<CursorEvent>>,
|
||||||
stop: mpsc::UnboundedSender<()>,
|
stop: mpsc::UnboundedSender<()>,
|
||||||
|
@ -56,10 +56,7 @@ impl Controller<CursorEvent> for CursorController {
|
||||||
if cursor.start > cursor.end {
|
if cursor.start > cursor.end {
|
||||||
std::mem::swap(&mut cursor.start, &mut cursor.end);
|
std::mem::swap(&mut cursor.start, &mut cursor.end);
|
||||||
}
|
}
|
||||||
Ok(self.op.send(CursorEvent {
|
Ok(self.op.send(cursor)?)
|
||||||
user: UserIdentity { id: self.user_id.to_string() },
|
|
||||||
position: cursor,
|
|
||||||
})?)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// try to receive without blocking, but will still block on stream mutex
|
/// try to receive without blocking, but will still block on stream mutex
|
||||||
|
|
|
@ -4,14 +4,14 @@ use tokio::sync::{mpsc, broadcast::{self}, Mutex, watch};
|
||||||
use tonic::{Streaming, async_trait};
|
use tonic::{Streaming, async_trait};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::{api::controller::ControllerWorker, errors::IgnorableError, proto::cursor::CursorEvent};
|
use crate::{api::controller::ControllerWorker, errors::IgnorableError, proto::cursor::{CursorPosition, CursorEvent}};
|
||||||
|
|
||||||
use super::controller::CursorController;
|
use super::controller::CursorController;
|
||||||
|
|
||||||
pub(crate) struct CursorWorker {
|
pub(crate) struct CursorWorker {
|
||||||
user_id: Uuid,
|
user_id: Uuid,
|
||||||
producer: mpsc::UnboundedSender<CursorEvent>,
|
producer: mpsc::UnboundedSender<CursorPosition>,
|
||||||
op: mpsc::UnboundedReceiver<CursorEvent>,
|
op: mpsc::UnboundedReceiver<CursorPosition>,
|
||||||
changed: watch::Sender<CursorEvent>,
|
changed: watch::Sender<CursorEvent>,
|
||||||
last_op: watch::Receiver<CursorEvent>,
|
last_op: watch::Receiver<CursorEvent>,
|
||||||
channel: Arc<broadcast::Sender<CursorEvent>>,
|
channel: Arc<broadcast::Sender<CursorEvent>>,
|
||||||
|
@ -41,7 +41,7 @@ impl CursorWorker {
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl ControllerWorker<CursorEvent> for CursorWorker {
|
impl ControllerWorker<CursorEvent> for CursorWorker {
|
||||||
type Controller = CursorController;
|
type Controller = CursorController;
|
||||||
type Tx = mpsc::Sender<CursorEvent>;
|
type Tx = mpsc::Sender<CursorPosition>;
|
||||||
type Rx = Streaming<CursorEvent>;
|
type Rx = Streaming<CursorEvent>;
|
||||||
|
|
||||||
fn subscribe(&self) -> CursorController {
|
fn subscribe(&self) -> CursorController {
|
||||||
|
|
53
src/lib.rs
53
src/lib.rs
|
@ -163,14 +163,55 @@ pub use woot;
|
||||||
#[cfg(feature = "transport")]
|
#[cfg(feature = "transport")]
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub mod proto {
|
pub mod proto {
|
||||||
pub mod user { tonic::include_proto!("user"); }
|
pub mod common {
|
||||||
|
tonic::include_proto!("common");
|
||||||
|
|
||||||
|
impl From<uuid::Uuid> for Identity {
|
||||||
|
fn from(id: uuid::Uuid) -> Self {
|
||||||
|
Identity { id: id.to_string() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&uuid::Uuid> for Identity {
|
||||||
|
fn from(id: &uuid::Uuid) -> Self {
|
||||||
|
Identity { id: id.to_string() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Identity> for uuid::Uuid {
|
||||||
|
fn from(value: Identity) -> Self {
|
||||||
|
uuid::Uuid::parse_str(&value.id).expect("invalid uuid in identity")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&Identity> for uuid::Uuid {
|
||||||
|
fn from(value: &Identity) -> Self {
|
||||||
|
uuid::Uuid::parse_str(&value.id).expect("invalid uuid in identity")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub mod files {
|
||||||
|
tonic::include_proto!("files");
|
||||||
|
|
||||||
|
impl From<String> for BufferNode {
|
||||||
|
fn from(value: String) -> Self {
|
||||||
|
BufferNode { path: value }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<BufferNode> for String {
|
||||||
|
fn from(value: BufferNode) -> Self {
|
||||||
|
value.path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub mod buffer { tonic::include_proto!("buffer"); }
|
||||||
pub mod cursor { tonic::include_proto!("cursor"); }
|
pub mod cursor { tonic::include_proto!("cursor"); }
|
||||||
pub mod files { tonic::include_proto!("files"); }
|
|
||||||
pub mod workspace { tonic::include_proto!("workspace"); }
|
pub mod workspace { tonic::include_proto!("workspace"); }
|
||||||
pub mod buffer_service { tonic::include_proto!("buffer_service"); }
|
pub mod auth { tonic::include_proto!("auth"); }
|
||||||
pub mod cursor_service { tonic::include_proto!("cursor_service"); }
|
|
||||||
pub mod workspace_service { tonic::include_proto!("workspace_service"); }
|
|
||||||
pub mod auth_service { tonic::include_proto!("auth_service"); }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub use errors::Error;
|
pub use errors::Error;
|
||||||
|
|
|
@ -2,11 +2,8 @@ use std::{collections::{BTreeMap, BTreeSet}, str::FromStr, sync::Arc};
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
use crate::{
|
use crate::{
|
||||||
proto::{user::UserIdentity, workspace::{AttachRequest, BufferListRequest, BufferPayload, Token, UserListRequest}},
|
api::controller::ControllerWorker, buffer::{self, worker::BufferWorker}, client::Services, cursor,
|
||||||
api::controller::ControllerWorker,
|
proto::{auth::Token, common::{Identity, Empty}, files::BufferNode, workspace::{WorkspaceEvent, workspace_event::{Event as WorkspaceEventInner, FileCreate, FileDelete, FileRename, UserJoin, UserLeave}}}
|
||||||
buffer::{self, worker::BufferWorker},
|
|
||||||
client::Services,
|
|
||||||
cursor
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//TODO may contain more info in the future
|
//TODO may contain more info in the future
|
||||||
|
@ -15,20 +12,6 @@ pub struct UserInfo {
|
||||||
pub uuid: Uuid
|
pub uuid: Uuid
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Uuid> for UserInfo {
|
|
||||||
fn from(uuid: Uuid) -> Self {
|
|
||||||
UserInfo {
|
|
||||||
uuid
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<UserIdentity> for Uuid {
|
|
||||||
fn from(uid: UserIdentity) -> Uuid {
|
|
||||||
Uuid::from_str(&uid.id).expect("expected an uuid")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Workspace {
|
pub struct Workspace {
|
||||||
id: String,
|
id: String,
|
||||||
user_id: Uuid,
|
user_id: Uuid,
|
||||||
|
@ -70,7 +53,7 @@ impl Workspace {
|
||||||
pub async fn create(&mut self, path: &str) -> crate::Result<()> {
|
pub async fn create(&mut self, path: &str) -> crate::Result<()> {
|
||||||
let mut workspace_client = self.services.workspace.clone();
|
let mut workspace_client = self.services.workspace.clone();
|
||||||
workspace_client.create_buffer(
|
workspace_client.create_buffer(
|
||||||
tonic::Request::new(BufferPayload { path: path.to_string() })
|
tonic::Request::new(BufferNode { path: path.to_string() })
|
||||||
).await?;
|
).await?;
|
||||||
|
|
||||||
// add to filetree
|
// add to filetree
|
||||||
|
@ -115,7 +98,7 @@ impl Workspace {
|
||||||
pub async fn fetch_buffers(&mut self) -> crate::Result<()> {
|
pub async fn fetch_buffers(&mut self) -> crate::Result<()> {
|
||||||
let mut workspace_client = self.services.workspace.clone();
|
let mut workspace_client = self.services.workspace.clone();
|
||||||
let buffers = workspace_client.list_buffers(
|
let buffers = workspace_client.list_buffers(
|
||||||
tonic::Request::new(BufferListRequest {})
|
tonic::Request::new(Empty {})
|
||||||
).await?.into_inner().buffers;
|
).await?.into_inner().buffers;
|
||||||
|
|
||||||
self.filetree.clear();
|
self.filetree.clear();
|
||||||
|
@ -130,7 +113,7 @@ impl Workspace {
|
||||||
pub async fn fetch_users(&mut self) -> crate::Result<()> {
|
pub async fn fetch_users(&mut self) -> crate::Result<()> {
|
||||||
let mut workspace_client = self.services.workspace.clone();
|
let mut workspace_client = self.services.workspace.clone();
|
||||||
let users = BTreeSet::from_iter(workspace_client.list_users(
|
let users = BTreeSet::from_iter(workspace_client.list_users(
|
||||||
tonic::Request::new(UserListRequest {})
|
tonic::Request::new(Empty {})
|
||||||
).await?.into_inner().users.into_iter().map(Uuid::from));
|
).await?.into_inner().users.into_iter().map(Uuid::from));
|
||||||
|
|
||||||
// only keep userinfo for users that still exist
|
// only keep userinfo for users that still exist
|
||||||
|
@ -150,7 +133,7 @@ impl Workspace {
|
||||||
pub async fn list_buffer_users(&mut self, path: &str) -> crate::Result<Vec<UserIdentity>> {
|
pub async fn list_buffer_users(&mut self, path: &str) -> crate::Result<Vec<UserIdentity>> {
|
||||||
let mut workspace_client = self.services.workspace.clone();
|
let mut workspace_client = self.services.workspace.clone();
|
||||||
let buffer_users = workspace_client.list_buffer_users(
|
let buffer_users = workspace_client.list_buffer_users(
|
||||||
tonic::Request::new(BufferPayload { path: path.to_string() })
|
tonic::Request::new(BufferNode { path: path.to_string() })
|
||||||
).await?.into_inner().users;
|
).await?.into_inner().users;
|
||||||
|
|
||||||
Ok(buffer_users)
|
Ok(buffer_users)
|
||||||
|
@ -167,8 +150,8 @@ impl Workspace {
|
||||||
/// delete a buffer
|
/// delete a buffer
|
||||||
pub async fn delete(&mut self, path: &str) -> crate::Result<()> {
|
pub async fn delete(&mut self, path: &str) -> crate::Result<()> {
|
||||||
let mut workspace_client = self.services.workspace.clone();
|
let mut workspace_client = self.services.workspace.clone();
|
||||||
workspace_client.delete(
|
workspace_client.delete_buffer(
|
||||||
tonic::Request::new(BufferPayload { path: path.to_string() })
|
tonic::Request::new(BufferNode { path: path.to_string() })
|
||||||
).await?;
|
).await?;
|
||||||
|
|
||||||
self.filetree.remove(path);
|
self.filetree.remove(path);
|
||||||
|
|
Loading…
Reference in a new issue