feat: websocket config (#99)
* chore: enable tls feature * chore: update ws client * chore: update ws client * chore: expost database entities * chore: update ws nginx config * chore: rename error file * chore: fix clippy
This commit is contained in:
parent
4a279bc108
commit
d3186cc07a
|
|
@ -4018,7 +4018,9 @@ checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"log",
|
"log",
|
||||||
|
"native-tls",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"tokio-native-tls",
|
||||||
"tungstenite",
|
"tungstenite",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -4166,6 +4168,7 @@ dependencies = [
|
||||||
"http",
|
"http",
|
||||||
"httparse",
|
"httparse",
|
||||||
"log",
|
"log",
|
||||||
|
"native-tls",
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
"sha1",
|
"sha1",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ mime = "0.3.17"
|
||||||
tracing = { version = "0.1" }
|
tracing = { version = "0.1" }
|
||||||
thiserror = "1.0.39"
|
thiserror = "1.0.39"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
tokio-tungstenite = { version = "0.20.1" }
|
tokio-tungstenite = { version = "0.20.1", features = ["native-tls"] }
|
||||||
tokio = { version = "1.26", features = ["full"] }
|
tokio = { version = "1.26", features = ["full"] }
|
||||||
futures-util = "0.3.26"
|
futures-util = "0.3.26"
|
||||||
futures-core = "0.3.26"
|
futures-core = "0.3.26"
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ use crate::notify::{ClientToken, TokenStateReceiver};
|
||||||
use database_entity::{AFUserProfileView, AFWorkspaceMember, InsertCollabParams};
|
use database_entity::{AFUserProfileView, AFWorkspaceMember, InsertCollabParams};
|
||||||
use database_entity::{AFWorkspaces, QueryCollabParams};
|
use database_entity::{AFWorkspaces, QueryCollabParams};
|
||||||
use database_entity::{DeleteCollabParams, RawData};
|
use database_entity::{DeleteCollabParams, RawData};
|
||||||
use shared_entity::error::AppError;
|
use shared_entity::app_error::AppError;
|
||||||
use shared_entity::error_code::url_missing_param;
|
use shared_entity::error_code::url_missing_param;
|
||||||
use shared_entity::error_code::ErrorCode;
|
use shared_entity::error_code::ErrorCode;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,11 +9,13 @@ pub mod ws;
|
||||||
pub use http::*;
|
pub use http::*;
|
||||||
|
|
||||||
pub mod error {
|
pub mod error {
|
||||||
pub use shared_entity::error::AppError;
|
pub use shared_entity::app_error::AppError;
|
||||||
pub use shared_entity::error_code::ErrorCode;
|
pub use shared_entity::error_code::ErrorCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Export all entities that will be used in the frontend application
|
||||||
pub mod entity {
|
pub mod entity {
|
||||||
|
pub use database_entity::*;
|
||||||
pub use gotrue_entity::*;
|
pub use gotrue_entity::*;
|
||||||
pub use shared_entity::*;
|
pub use shared_entity::*;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
use futures_util::{SinkExt, StreamExt};
|
use futures_util::{SinkExt, StreamExt};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
|
use parking_lot::RwLock;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use std::sync::{Arc, Weak};
|
use std::sync::{Arc, Weak};
|
||||||
|
|
@ -12,7 +13,7 @@ use crate::ws::state::{ConnectState, ConnectStateNotify};
|
||||||
use crate::ws::{BusinessID, ClientRealtimeMessage, WSError, WebSocketChannel};
|
use crate::ws::{BusinessID, ClientRealtimeMessage, WSError, WebSocketChannel};
|
||||||
use tokio::sync::broadcast::{channel, Receiver, Sender};
|
use tokio::sync::broadcast::{channel, Receiver, Sender};
|
||||||
|
|
||||||
use tokio::sync::{oneshot, Mutex, RwLock};
|
use tokio::sync::{oneshot, Mutex};
|
||||||
use tokio_retry::strategy::FixedInterval;
|
use tokio_retry::strategy::FixedInterval;
|
||||||
use tokio_retry::{Condition, RetryIf};
|
use tokio_retry::{Condition, RetryIf};
|
||||||
use tokio_tungstenite::tungstenite::protocol::frame::coding::CloseCode;
|
use tokio_tungstenite::tungstenite::protocol::frame::coding::CloseCode;
|
||||||
|
|
@ -43,10 +44,11 @@ impl Default for WSClientConfig {
|
||||||
|
|
||||||
type ChannelByObjectId = HashMap<String, Weak<WebSocketChannel>>;
|
type ChannelByObjectId = HashMap<String, Weak<WebSocketChannel>>;
|
||||||
pub type WSConnectStateReceiver = Receiver<ConnectState>;
|
pub type WSConnectStateReceiver = Receiver<ConnectState>;
|
||||||
|
|
||||||
pub struct WSClient {
|
pub struct WSClient {
|
||||||
addr: Arc<parking_lot::Mutex<Option<String>>>,
|
addr: Arc<parking_lot::Mutex<Option<String>>>,
|
||||||
config: WSClientConfig,
|
config: WSClientConfig,
|
||||||
state_notify: Arc<Mutex<ConnectStateNotify>>,
|
state_notify: Arc<parking_lot::Mutex<ConnectStateNotify>>,
|
||||||
/// Sender used to send messages to the websocket.
|
/// Sender used to send messages to the websocket.
|
||||||
sender: Sender<Message>,
|
sender: Sender<Message>,
|
||||||
channels: Arc<RwLock<HashMap<BusinessID, ChannelByObjectId>>>,
|
channels: Arc<RwLock<HashMap<BusinessID, ChannelByObjectId>>>,
|
||||||
|
|
@ -57,13 +59,13 @@ pub struct WSClient {
|
||||||
impl WSClient {
|
impl WSClient {
|
||||||
pub fn new(config: WSClientConfig) -> Self {
|
pub fn new(config: WSClientConfig) -> Self {
|
||||||
let (sender, _) = channel(config.buffer_capacity);
|
let (sender, _) = channel(config.buffer_capacity);
|
||||||
let state = Arc::new(Mutex::new(ConnectStateNotify::new()));
|
let state_notify = Arc::new(parking_lot::Mutex::new(ConnectStateNotify::new()));
|
||||||
let channels = Arc::new(RwLock::new(HashMap::new()));
|
let channels = Arc::new(RwLock::new(HashMap::new()));
|
||||||
let ping = Arc::new(Mutex::new(None));
|
let ping = Arc::new(Mutex::new(None));
|
||||||
WSClient {
|
WSClient {
|
||||||
addr: Arc::new(parking_lot::Mutex::new(None)),
|
addr: Arc::new(parking_lot::Mutex::new(None)),
|
||||||
config,
|
config,
|
||||||
state_notify: state,
|
state_notify,
|
||||||
sender,
|
sender,
|
||||||
channels,
|
channels,
|
||||||
ping,
|
ping,
|
||||||
|
|
@ -118,7 +120,6 @@ impl WSClient {
|
||||||
if let Some(channels) = weak_channels.upgrade() {
|
if let Some(channels) = weak_channels.upgrade() {
|
||||||
if let Some(channel) = channels
|
if let Some(channel) = channels
|
||||||
.read()
|
.read()
|
||||||
.await
|
|
||||||
.get(&msg.business_id)
|
.get(&msg.business_id)
|
||||||
.and_then(|map| map.get(&msg.object_id))
|
.and_then(|map| map.get(&msg.object_id))
|
||||||
{
|
{
|
||||||
|
|
@ -181,7 +182,7 @@ impl WSClient {
|
||||||
|
|
||||||
/// Return a [WebSocketChannel] that can be used to send messages to the websocket. Caller should
|
/// Return a [WebSocketChannel] that can be used to send messages to the websocket. Caller should
|
||||||
/// keep the channel alive as long as it wants to receive messages from the websocket.
|
/// keep the channel alive as long as it wants to receive messages from the websocket.
|
||||||
pub async fn subscribe(
|
pub fn subscribe(
|
||||||
&self,
|
&self,
|
||||||
business_id: BusinessID,
|
business_id: BusinessID,
|
||||||
object_id: String,
|
object_id: String,
|
||||||
|
|
@ -190,19 +191,18 @@ impl WSClient {
|
||||||
self
|
self
|
||||||
.channels
|
.channels
|
||||||
.write()
|
.write()
|
||||||
.await
|
|
||||||
.entry(business_id)
|
.entry(business_id)
|
||||||
.or_insert_with(HashMap::new)
|
.or_insert_with(HashMap::new)
|
||||||
.insert(object_id, Arc::downgrade(&channel));
|
.insert(object_id, Arc::downgrade(&channel));
|
||||||
Ok(channel)
|
Ok(channel)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn subscribe_connect_state(&self) -> WSConnectStateReceiver {
|
pub fn subscribe_connect_state(&self) -> WSConnectStateReceiver {
|
||||||
self.state_notify.lock().await.subscribe()
|
self.state_notify.lock().subscribe()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn is_connected(&self) -> bool {
|
pub fn is_connected(&self) -> bool {
|
||||||
self.state_notify.lock().await.state.is_connected()
|
self.state_notify.lock().state.is_connected()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn disconnect(&self) {
|
pub async fn disconnect(&self) {
|
||||||
|
|
@ -222,7 +222,7 @@ impl WSClient {
|
||||||
|
|
||||||
async fn set_state(&self, state: ConnectState) {
|
async fn set_state(&self, state: ConnectState) {
|
||||||
trace!("websocket state: {:?}", state);
|
trace!("websocket state: {:?}", state);
|
||||||
self.state_notify.lock().await.set_state(state);
|
self.state_notify.lock().set_state(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ pub(crate) struct ServerFixIntervalPing {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
stop_tx: tokio::sync::mpsc::Sender<()>,
|
stop_tx: tokio::sync::mpsc::Sender<()>,
|
||||||
stop_rx: Option<tokio::sync::mpsc::Receiver<()>>,
|
stop_rx: Option<tokio::sync::mpsc::Receiver<()>>,
|
||||||
state: Arc<Mutex<ConnectStateNotify>>,
|
state: Arc<parking_lot::Mutex<ConnectStateNotify>>,
|
||||||
ping_count: Arc<Mutex<u32>>,
|
ping_count: Arc<Mutex<u32>>,
|
||||||
maximum_ping_count: u32,
|
maximum_ping_count: u32,
|
||||||
}
|
}
|
||||||
|
|
@ -19,7 +19,7 @@ pub(crate) struct ServerFixIntervalPing {
|
||||||
impl ServerFixIntervalPing {
|
impl ServerFixIntervalPing {
|
||||||
pub(crate) fn new(
|
pub(crate) fn new(
|
||||||
duration: Duration,
|
duration: Duration,
|
||||||
state: Arc<Mutex<ConnectStateNotify>>,
|
state: Arc<parking_lot::Mutex<ConnectStateNotify>>,
|
||||||
sender: Sender<Message>,
|
sender: Sender<Message>,
|
||||||
maximum_ping_count: u32,
|
maximum_ping_count: u32,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
|
@ -58,7 +58,7 @@ impl ServerFixIntervalPing {
|
||||||
let mut lock = ping_count.lock().await;
|
let mut lock = ping_count.lock().await;
|
||||||
if *lock >= reconnect_per_ping {
|
if *lock >= reconnect_per_ping {
|
||||||
if let Some(state) =weak_state.upgrade() {
|
if let Some(state) =weak_state.upgrade() {
|
||||||
state.lock().await.set_state(ConnectState::PingTimeout);
|
state.lock().set_state(ConnectState::PingTimeout);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
*lock +=1;
|
*lock +=1;
|
||||||
|
|
@ -73,7 +73,7 @@ impl ServerFixIntervalPing {
|
||||||
*lock = 0;
|
*lock = 0;
|
||||||
|
|
||||||
if let Some(state) =weak_state.upgrade() {
|
if let Some(state) =weak_state.upgrade() {
|
||||||
state.lock().await.set_state(ConnectState::Connected);
|
state.lock().set_state(ConnectState::Connected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ use std::ops::Deref;
|
||||||
use validator::{Validate, ValidationError};
|
use validator::{Validate, ValidationError};
|
||||||
|
|
||||||
pub type RawData = Vec<u8>;
|
pub type RawData = Vec<u8>;
|
||||||
pub mod error;
|
pub mod database_error;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Validate, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Validate, Serialize, Deserialize)]
|
||||||
pub struct InsertCollabParams {
|
pub struct InsertCollabParams {
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ use anyhow::Context;
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use collab::core::collab::MutexCollab;
|
use collab::core::collab::MutexCollab;
|
||||||
use collab_define::CollabType;
|
use collab_define::CollabType;
|
||||||
use database_entity::error::DatabaseError;
|
use database_entity::database_error::DatabaseError;
|
||||||
use database_entity::{
|
use database_entity::{
|
||||||
AFCollabSnapshots, InsertCollabParams, InsertSnapshotParams, QueryCollabParams,
|
AFCollabSnapshots, InsertCollabParams, InsertSnapshotParams, QueryCollabParams,
|
||||||
QueryObjectSnapshotParams, QuerySnapshotParams, RawData,
|
QueryObjectSnapshotParams, QuerySnapshotParams, RawData,
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ use std::{ops::DerefMut, str::FromStr};
|
||||||
|
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use database_entity::{
|
use database_entity::{
|
||||||
error::DatabaseError, AFCollabSnapshot, AFCollabSnapshots, InsertCollabParams,
|
database_error::DatabaseError, AFCollabSnapshot, AFCollabSnapshots, InsertCollabParams,
|
||||||
};
|
};
|
||||||
use sqlx::{PgPool, Transaction};
|
use sqlx::{PgPool, Transaction};
|
||||||
use tracing::trace;
|
use tracing::trace;
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ use bytes::Bytes;
|
||||||
use collab::core::collab::TransactionMutExt;
|
use collab::core::collab::TransactionMutExt;
|
||||||
use collab::core::origin::CollabOrigin;
|
use collab::core::origin::CollabOrigin;
|
||||||
use collab::preclude::{CollabPlugin, Doc, TransactionMut};
|
use collab::preclude::{CollabPlugin, Doc, TransactionMut};
|
||||||
use database_entity::error::DatabaseError;
|
use database_entity::database_error::DatabaseError;
|
||||||
|
|
||||||
use collab::sync_protocol::awareness::Awareness;
|
use collab::sync_protocol::awareness::Awareness;
|
||||||
use collab_define::CollabType;
|
use collab_define::CollabType;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use collab::error::CollabError;
|
use collab::error::CollabError;
|
||||||
use database_entity::error::DatabaseError;
|
use database_entity::database_error::DatabaseError;
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
pub enum RealtimeError {
|
pub enum RealtimeError {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use database_entity::error::DatabaseError;
|
use database_entity::database_error::DatabaseError;
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
use std::num::ParseIntError;
|
use std::num::ParseIntError;
|
||||||
use std::time::SystemTimeError;
|
use std::time::SystemTimeError;
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::error::AppError;
|
use crate::app_error::AppError;
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use serde_repr::{Deserialize_repr, Serialize_repr};
|
use serde_repr::{Deserialize_repr, Serialize_repr};
|
||||||
|
|
||||||
use crate::error::AppError;
|
use crate::app_error::AppError;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Error, Default, PartialEq, Eq, Serialize_repr, Deserialize_repr)]
|
#[derive(Clone, Copy, Debug, Error, Default, PartialEq, Eq, Serialize_repr, Deserialize_repr)]
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
|
pub mod app_error;
|
||||||
pub mod data;
|
pub mod data;
|
||||||
pub mod dto;
|
pub mod dto;
|
||||||
pub mod error;
|
|
||||||
pub mod error_code;
|
pub mod error_code;
|
||||||
|
|
||||||
#[cfg(feature = "cloud")]
|
#[cfg(feature = "cloud")]
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,16 @@ http {
|
||||||
proxy_pass http://gotrue:9999;
|
proxy_pass http://gotrue:9999;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# WebSocket
|
||||||
|
location /ws {
|
||||||
|
proxy_pass http://appflowy_cloud;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection "Upgrade";
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_read_timeout 86400;
|
||||||
|
}
|
||||||
|
|
||||||
# AppFlowy-Cloud
|
# AppFlowy-Cloud
|
||||||
location / {
|
location / {
|
||||||
proxy_pass http://appflowy_cloud:8000;
|
proxy_pass http://appflowy_cloud:8000;
|
||||||
|
|
|
||||||
|
|
@ -6,13 +6,13 @@ use actix_web::web::{Data, Json};
|
||||||
use actix_web::Result;
|
use actix_web::Result;
|
||||||
use actix_web::{web, Scope};
|
use actix_web::{web, Scope};
|
||||||
use database::collab::CollabStorage;
|
use database::collab::CollabStorage;
|
||||||
use database_entity::error::DatabaseError;
|
use database_entity::database_error::DatabaseError;
|
||||||
use database_entity::{
|
use database_entity::{
|
||||||
AFCollabSnapshots, DeleteCollabParams, InsertCollabParams, QueryCollabParams,
|
AFCollabSnapshots, DeleteCollabParams, InsertCollabParams, QueryCollabParams,
|
||||||
QueryObjectSnapshotParams, QuerySnapshotParams, RawData,
|
QueryObjectSnapshotParams, QuerySnapshotParams, RawData,
|
||||||
};
|
};
|
||||||
|
use shared_entity::app_error::AppError;
|
||||||
use shared_entity::data::AppResponse;
|
use shared_entity::data::AppResponse;
|
||||||
use shared_entity::error::AppError;
|
|
||||||
use shared_entity::error_code::ErrorCode;
|
use shared_entity::error_code::ErrorCode;
|
||||||
use tracing::{debug, instrument};
|
use tracing::{debug, instrument};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
use crate::biz;
|
use crate::biz;
|
||||||
use crate::state::AppState;
|
use crate::state::AppState;
|
||||||
use database_entity::{AFWorkspaceMember, AFWorkspaces};
|
use database_entity::{AFWorkspaceMember, AFWorkspaces};
|
||||||
|
use shared_entity::app_error::AppError;
|
||||||
use shared_entity::data::{AppResponse, JsonAppResponse};
|
use shared_entity::data::{AppResponse, JsonAppResponse};
|
||||||
use shared_entity::dto::WorkspaceMembersParams;
|
use shared_entity::dto::WorkspaceMembersParams;
|
||||||
use shared_entity::error::AppError;
|
|
||||||
use sqlx::types::uuid;
|
use sqlx::types::uuid;
|
||||||
|
|
||||||
use crate::component::auth::jwt::UserUuid;
|
use crate::component::auth::jwt::UserUuid;
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ use database_entity::{
|
||||||
AFCollabSnapshots, DeleteCollabParams, InsertCollabParams, QueryObjectSnapshotParams,
|
AFCollabSnapshots, DeleteCollabParams, InsertCollabParams, QueryObjectSnapshotParams,
|
||||||
QuerySnapshotParams,
|
QuerySnapshotParams,
|
||||||
};
|
};
|
||||||
use shared_entity::{error::AppError, error_code::ErrorCode};
|
use shared_entity::{app_error::AppError, error_code::ErrorCode};
|
||||||
use sqlx::{types::Uuid, PgPool};
|
use sqlx::{types::Uuid, PgPool};
|
||||||
use validator::Validate;
|
use validator::Validate;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ use futures_util::Stream;
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use database::{file_storage, user::uid_from_uuid};
|
use database::{file_storage, user::uid_from_uuid};
|
||||||
use s3::request::{ResponseData, ResponseDataStream};
|
use s3::request::{ResponseData, ResponseDataStream};
|
||||||
use shared_entity::{error::AppError, error_code::ErrorCode};
|
use shared_entity::{app_error::AppError, error_code::ErrorCode};
|
||||||
use sqlx::types::uuid;
|
use sqlx::types::uuid;
|
||||||
use tokio_stream::StreamExt;
|
use tokio_stream::StreamExt;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ use database::{
|
||||||
};
|
};
|
||||||
use database_entity::AFUserProfileView;
|
use database_entity::AFUserProfileView;
|
||||||
use gotrue::api::Client;
|
use gotrue::api::Client;
|
||||||
use shared_entity::error::AppError;
|
use shared_entity::app_error::AppError;
|
||||||
|
|
||||||
use sqlx::{types::uuid, PgPool};
|
use sqlx::{types::uuid, PgPool};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ use database::workspace::{
|
||||||
select_user_is_workspace_owner, select_workspace_members,
|
select_user_is_workspace_owner, select_workspace_members,
|
||||||
};
|
};
|
||||||
use database_entity::{AFRole, AFWorkspaceMember, AFWorkspaces};
|
use database_entity::{AFRole, AFWorkspaceMember, AFWorkspaces};
|
||||||
use shared_entity::{error::AppError, error_code::ErrorCode};
|
use shared_entity::{app_error::AppError, error_code::ErrorCode};
|
||||||
use sqlx::{types::uuid, PgPool};
|
use sqlx::{types::uuid, PgPool};
|
||||||
|
|
||||||
pub async fn get_workspaces(
|
pub async fn get_workspaces(
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ async fn realtime_connect_test() {
|
||||||
ping_per_secs: 6,
|
ping_per_secs: 6,
|
||||||
retry_connect_per_pings: 5,
|
retry_connect_per_pings: 5,
|
||||||
});
|
});
|
||||||
let mut state = ws_client.subscribe_connect_state().await;
|
let mut state = ws_client.subscribe_connect_state();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
|
|
@ -38,7 +38,7 @@ async fn realtime_disconnect_test() {
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let mut state = ws_client.subscribe_connect_state().await;
|
let mut state = ws_client.subscribe_connect_state();
|
||||||
loop {
|
loop {
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
_ = ws_client.disconnect() => {},
|
_ = ws_client.disconnect() => {},
|
||||||
|
|
|
||||||
|
|
@ -90,7 +90,7 @@ impl TestClient {
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub(crate) async fn wait_ws_connected(&self) {
|
pub(crate) async fn wait_ws_connected(&self) {
|
||||||
let mut connect_state = self.ws_client.subscribe_connect_state().await;
|
let mut connect_state = self.ws_client.subscribe_connect_state();
|
||||||
|
|
||||||
const TIMEOUT_DURATION: Duration = Duration::from_secs(10);
|
const TIMEOUT_DURATION: Duration = Duration::from_secs(10);
|
||||||
while let Ok(Ok(state)) = timeout(TIMEOUT_DURATION, connect_state.recv()).await {
|
while let Ok(Ok(state)) = timeout(TIMEOUT_DURATION, connect_state.recv()).await {
|
||||||
|
|
@ -124,13 +124,12 @@ impl TestClient {
|
||||||
let handler = self
|
let handler = self
|
||||||
.ws_client
|
.ws_client
|
||||||
.subscribe(BusinessID::CollabId, object_id.to_string())
|
.subscribe(BusinessID::CollabId, object_id.to_string())
|
||||||
.await
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let (sink, stream) = (handler.sink(), handler.stream());
|
let (sink, stream) = (handler.sink(), handler.stream());
|
||||||
let origin = CollabOrigin::Client(CollabClient::new(uid, self.device_id.clone()));
|
let origin = CollabOrigin::Client(CollabClient::new(uid, self.device_id.clone()));
|
||||||
let collab = Arc::new(MutexCollab::new(origin.clone(), object_id, vec![]));
|
let collab = Arc::new(MutexCollab::new(origin.clone(), object_id, vec![]));
|
||||||
|
|
||||||
let ws_connect_state = self.ws_client.subscribe_connect_state().await;
|
let ws_connect_state = self.ws_client.subscribe_connect_state();
|
||||||
let object = SyncObject::new(object_id, workspace_id, collab_type, &self.device_id);
|
let object = SyncObject::new(object_id, workspace_id, collab_type, &self.device_id);
|
||||||
let sync_plugin = SyncPlugin::new(
|
let sync_plugin = SyncPlugin::new(
|
||||||
origin.clone(),
|
origin.clone(),
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue