chore: code cleanup

This commit is contained in:
Bartosz Sypytkowski 2024-10-14 08:41:23 +02:00
parent 3cea53cd13
commit 854215705c
9 changed files with 108 additions and 131 deletions

View File

@ -9,9 +9,9 @@ edition = "2021"
actix.workspace = true actix.workspace = true
actix-web.workspace = true actix-web.workspace = true
actix-http = { workspace = true, default-features = false, features = [ actix-http = { workspace = true, default-features = false, features = [
"openssl", "openssl",
"compress-brotli", "compress-brotli",
"compress-gzip", "compress-gzip",
] } ] }
actix-rt = "2.9.0" actix-rt = "2.9.0"
actix-web-actors = { version = "4.3" } actix-web-actors = { version = "4.3" }
@ -28,20 +28,20 @@ serde_repr.workspace = true
serde.workspace = true serde.workspace = true
tokio = { workspace = true, features = [ tokio = { workspace = true, features = [
"macros", "macros",
"rt-multi-thread", "rt-multi-thread",
"sync", "sync",
"fs", "fs",
"time", "time",
"full", "full",
] } ] }
tokio-stream.workspace = true tokio-stream.workspace = true
tokio-util = { version = "0.7.10", features = ["io"] } tokio-util = { version = "0.7.10", features = ["io"] }
futures-util = { workspace = true, features = ["std", "io"] } futures-util = { workspace = true, features = ["std", "io"] }
once_cell = "1.19.0" once_cell = "1.19.0"
chrono = { version = "0.4.37", features = [ chrono = { version = "0.4.37", features = [
"serde", "serde",
"clock", "clock",
], default-features = false } ], default-features = false }
derive_more = { version = "0.99" } derive_more = { version = "0.99" }
secrecy.workspace = true secrecy.workspace = true
@ -49,10 +49,10 @@ rand = { version = "0.8", features = ["std_rng"] }
anyhow = "1.0.79" anyhow = "1.0.79"
thiserror = "1.0.56" thiserror = "1.0.56"
reqwest = { workspace = true, features = [ reqwest = { workspace = true, features = [
"json", "json",
"rustls-tls", "rustls-tls",
"cookies", "cookies",
"stream", "stream",
] } ] }
unicode-segmentation = "1.10" unicode-segmentation = "1.10"
lazy_static.workspace = true lazy_static.workspace = true
@ -62,31 +62,31 @@ bytes = "1.5.0"
rcgen = { version = "0.10.0", features = ["pem", "x509-parser"] } rcgen = { version = "0.10.0", features = ["pem", "x509-parser"] }
mime = "0.3.17" mime = "0.3.17"
aws-sdk-s3 = { version = "1.36.0", features = [ aws-sdk-s3 = { version = "1.36.0", features = [
"behavior-version-latest", "behavior-version-latest",
"rt-tokio", "rt-tokio",
] } ] }
aws-config = { version = "1.5.1", features = ["behavior-version-latest"] } aws-config = { version = "1.5.1", features = ["behavior-version-latest"] }
redis = { workspace = true, features = [ redis = { workspace = true, features = [
"json", "json",
"tokio-comp", "tokio-comp",
"connection-manager", "connection-manager",
] } ] }
tracing = { version = "0.1.40", features = ["log"] } tracing = { version = "0.1.40", features = ["log"] }
tracing-subscriber = { version = "0.3.18", features = [ tracing-subscriber = { version = "0.3.18", features = [
"registry", "registry",
"env-filter", "env-filter",
"ansi", "ansi",
"json", "json",
"tracing-log", "tracing-log",
] } ] }
tracing-bunyan-formatter = "0.3.9" tracing-bunyan-formatter = "0.3.9"
sqlx = { workspace = true, default-features = false, features = [ sqlx = { workspace = true, default-features = false, features = [
"runtime-tokio-rustls", "runtime-tokio-rustls",
"macros", "macros",
"postgres", "postgres",
"uuid", "uuid",
"chrono", "chrono",
"migrate", "migrate",
] } ] }
async-trait.workspace = true async-trait.workspace = true
prometheus-client.workspace = true prometheus-client.workspace = true
@ -129,10 +129,10 @@ infra = { path = "libs/infra" }
authentication.workspace = true authentication.workspace = true
access-control.workspace = true access-control.workspace = true
app-error = { workspace = true, features = [ app-error = { workspace = true, features = [
"sqlx_error", "sqlx_error",
"actix_web_error", "actix_web_error",
"tokio_error", "tokio_error",
"appflowy_ai_error", "appflowy_ai_error",
] } ] }
shared-entity = { path = "libs/shared-entity", features = ["cloud"] } shared-entity = { path = "libs/shared-entity", features = ["cloud"] }
workspace-template = { workspace = true } workspace-template = { workspace = true }
@ -164,11 +164,11 @@ assert-json-diff = "2.0.2"
scraper = "0.17.1" scraper = "0.17.1"
client-api-test = { path = "libs/client-api-test", features = ["collab-sync"] } client-api-test = { path = "libs/client-api-test", features = ["collab-sync"] }
client-api = { path = "libs/client-api", features = [ client-api = { path = "libs/client-api", features = [
"collab-sync", "collab-sync",
"test_util", "test_util",
"sync_verbose_log", "sync_verbose_log",
"test_fast_sync", "test_fast_sync",
"enable_brotli", "enable_brotli",
] } ] }
opener = "0.6.1" opener = "0.6.1"
image = "0.23.14" image = "0.23.14"
@ -190,38 +190,38 @@ path = "src/lib.rs"
[workspace] [workspace]
members = [ members = [
# libs # libs
"libs/snowflake", "libs/snowflake",
"libs/collab-rt-entity", "libs/collab-rt-entity",
"libs/database", "libs/database",
"libs/database-entity", "libs/database-entity",
"libs/client-api", "libs/client-api",
"libs/infra", "libs/infra",
"libs/shared-entity", "libs/shared-entity",
"libs/gotrue", "libs/gotrue",
"libs/gotrue-entity", "libs/gotrue-entity",
"admin_frontend", "admin_frontend",
"libs/app-error", "libs/app-error",
"libs/workspace-template", "libs/workspace-template",
"libs/encrypt", "libs/encrypt",
"libs/authentication", "libs/authentication",
"libs/access-control", "libs/access-control",
"libs/collab-rt-protocol", "libs/collab-rt-protocol",
"libs/collab-stream", "libs/collab-stream",
"libs/client-websocket", "libs/client-websocket",
"libs/client-api-test", "libs/client-api-test",
"libs/wasm-test", "libs/wasm-test",
"libs/client-api-wasm", "libs/client-api-wasm",
"libs/appflowy-ai-client", "libs/appflowy-ai-client",
"libs/client-api-entity", "libs/client-api-entity",
# services # services
"services/appflowy-history", "services/appflowy-history",
"services/appflowy-collaborate", "services/appflowy-collaborate",
"services/appflowy-worker", "services/appflowy-worker",
# xtask # xtask
"xtask", "xtask",
"libs/tonic-proto", "libs/tonic-proto",
"libs/mailer", "libs/mailer",
] ]
[workspace.dependencies] [workspace.dependencies]
@ -250,9 +250,9 @@ uuid = { version = "1.6.1", features = ["v4", "v5"] }
anyhow = "1.0.79" anyhow = "1.0.79"
actix = "0.13.3" actix = "0.13.3"
actix-web = { version = "4.5.1", default-features = false, features = [ actix-web = { version = "4.5.1", default-features = false, features = [
"openssl", "openssl",
"compress-brotli", "compress-brotli",
"compress-gzip", "compress-gzip",
] } ] }
actix-http = { version = "3.6.0", default-features = false } actix-http = { version = "3.6.0", default-features = false }
tokio = { version = "1.36.0", features = ["sync"] } tokio = { version = "1.36.0", features = ["sync"] }

View File

@ -3,13 +3,12 @@ use crate::error::StreamError;
use crate::lease::{Lease, LeaseAcquisition}; use crate::lease::{Lease, LeaseAcquisition};
use crate::model::{ use crate::model::{
AwarenessStreamUpdate, AwarenessStreamUpdateBatch, CollabStreamUpdate, CollabStreamUpdateBatch, AwarenessStreamUpdate, AwarenessStreamUpdateBatch, CollabStreamUpdate, CollabStreamUpdateBatch,
CollabUpdateEvent, MessageId, MessageId,
}; };
use crate::pubsub::{CollabStreamPub, CollabStreamSub};
use crate::stream_group::{StreamConfig, StreamGroup}; use crate::stream_group::{StreamConfig, StreamGroup};
use futures::Stream; use futures::Stream;
use redis::aio::ConnectionManager; use redis::aio::ConnectionManager;
use redis::streams::{StreamRangeReply, StreamReadOptions, StreamReadReply}; use redis::streams::{StreamRangeReply, StreamReadOptions};
use redis::{AsyncCommands, FromRedisValue}; use redis::{AsyncCommands, FromRedisValue};
use std::time::Duration; use std::time::Duration;
use tracing::error; use tracing::error;

View File

@ -1,11 +1,8 @@
use crate::client::CollabRedisStream;
use crate::error::StreamError; use crate::error::StreamError;
use async_trait::async_trait; use async_trait::async_trait;
use chrono::{DateTime, NaiveDateTime};
use redis::aio::ConnectionManager; use redis::aio::ConnectionManager;
use redis::{RedisResult, Value}; use redis::Value;
use std::sync::Arc; use std::time::{Duration, SystemTime, UNIX_EPOCH};
use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
const RELEASE_SCRIPT: &str = r#" const RELEASE_SCRIPT: &str = r#"
if redis.call("GET", KEYS[1]) == ARGV[1] then if redis.call("GET", KEYS[1]) == ARGV[1] then

View File

@ -77,8 +77,6 @@ pub async fn run_actix_server(
rt_cmd_recv, rt_cmd_recv,
state.redis_connection_manager.clone(), state.redis_connection_manager.clone(),
Duration::from_secs(config.collab.group_persistence_interval_secs), Duration::from_secs(config.collab.group_persistence_interval_secs),
config.collab.edit_state_max_count,
config.collab.edit_state_max_secs,
state.indexer_provider.clone(), state.indexer_provider.clone(),
) )
.await .await

View File

@ -2,7 +2,6 @@ use async_stream::stream;
use collab::core::origin::CollabOrigin; use collab::core::origin::CollabOrigin;
use collab::entity::EncodedCollab; use collab::entity::EncodedCollab;
use dashmap::DashMap; use dashmap::DashMap;
use futures::channel::mpsc::{SendError, Sender};
use futures::Sink; use futures::Sink;
use futures_util::StreamExt; use futures_util::StreamExt;
use std::collections::HashMap; use std::collections::HashMap;
@ -333,22 +332,22 @@ impl<T> Sink<T> for NullSender<T> {
type Error = RealtimeError; type Error = RealtimeError;
#[inline] #[inline]
fn poll_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { fn poll_ready(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
Poll::Ready(Ok(())) Poll::Ready(Ok(()))
} }
#[inline] #[inline]
fn start_send(self: Pin<&mut Self>, item: T) -> Result<(), Self::Error> { fn start_send(self: Pin<&mut Self>, _: T) -> Result<(), Self::Error> {
Ok(()) Ok(())
} }
#[inline] #[inline]
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { fn poll_flush(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
Poll::Ready(Ok(())) Poll::Ready(Ok(()))
} }
#[inline] #[inline]
fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { fn poll_close(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
Poll::Ready(Ok(())) Poll::Ready(Ok(()))
} }
} }

View File

@ -1,11 +1,9 @@
use crate::error::RealtimeError; use crate::error::RealtimeError;
use crate::indexer::{Indexer, IndexerProvider}; use crate::indexer::Indexer;
use crate::metrics::CollabRealtimeMetrics; use crate::metrics::CollabRealtimeMetrics;
use crate::state::RedisConnectionManager;
use anyhow::anyhow; use anyhow::anyhow;
use app_error::AppError; use app_error::AppError;
use arc_swap::{ArcSwap, ArcSwapAny, ArcSwapOption}; use arc_swap::ArcSwap;
use bytes::Bytes;
use collab::core::collab::DataSource; use collab::core::collab::DataSource;
use collab::core::origin::CollabOrigin; use collab::core::origin::CollabOrigin;
use collab::entity::EncodedCollab; use collab::entity::EncodedCollab;
@ -17,7 +15,7 @@ use collab_rt_entity::{
AckCode, AwarenessSync, BroadcastSync, CollabAck, MessageByObjectId, MsgId, AckCode, AwarenessSync, BroadcastSync, CollabAck, MessageByObjectId, MsgId,
}; };
use collab_rt_entity::{ClientCollabMessage, CollabMessage}; use collab_rt_entity::{ClientCollabMessage, CollabMessage};
use collab_rt_protocol::{decode_update, Message, MessageReader, RTProtocolError, SyncMessage}; use collab_rt_protocol::{Message, MessageReader, RTProtocolError, SyncMessage};
use collab_stream::client::CollabRedisStream; use collab_stream::client::CollabRedisStream;
use collab_stream::collab_update_sink::{AwarenessUpdateSink, CollabUpdateSink}; use collab_stream::collab_update_sink::{AwarenessUpdateSink, CollabUpdateSink};
use collab_stream::error::StreamError; use collab_stream::error::StreamError;
@ -29,24 +27,19 @@ use collab_stream::stream_group::StreamGroup;
use dashmap::DashMap; use dashmap::DashMap;
use database::collab::{CollabStorage, GetCollabOrigin}; use database::collab::{CollabStorage, GetCollabOrigin};
use database_entity::dto::{ use database_entity::dto::{
AFCollabEmbeddings, CollabParams, InsertSnapshotParams, QueryCollabParams, SnapshotData, AFCollabEmbeddings, CollabParams, InsertSnapshotParams, QueryCollabParams,
}; };
use futures::{pin_mut, Sink, Stream}; use futures::{pin_mut, Sink, Stream};
use futures_util::{SinkExt, StreamExt}; use futures_util::{SinkExt, StreamExt};
use std::collections::VecDeque; use std::collections::VecDeque;
use std::fmt::{Display, Formatter}; use std::sync::atomic::{AtomicU32, Ordering};
use std::os::linux::raw::stat;
use std::pin::Pin;
use std::sync::atomic::{AtomicBool, AtomicI64, AtomicU32, Ordering};
use std::sync::Arc; use std::sync::Arc;
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
use tokio::sync::{mpsc, Mutex}; use tokio::sync::mpsc;
use tokio::time::{interval, MissedTickBehavior}; use tokio::time::MissedTickBehavior;
use tokio_util::sync::{CancellationToken, DropGuard}; use tokio_util::sync::CancellationToken;
use tracing::{error, event, info, trace}; use tracing::{error, info, trace};
use yrs::encoding::read::Error; use yrs::updates::decoder::{Decode, DecoderV1};
use yrs::sync::AwarenessUpdate;
use yrs::updates::decoder::{Decode, DecoderV1, DecoderV2};
use yrs::updates::encoder::{Encode, Encoder, EncoderV1}; use yrs::updates::encoder::{Encode, Encoder, EncoderV1};
use yrs::{ReadTxn, StateVector, Update}; use yrs::{ReadTxn, StateVector, Update};
@ -100,6 +93,7 @@ impl CollabGroup {
S: CollabStorage, S: CollabStorage,
{ {
let persister = CollabPersister::new( let persister = CollabPersister::new(
uid,
workspace_id.clone(), workspace_id.clone(),
object_id.clone(), object_id.clone(),
collab_type.clone(), collab_type.clone(),
@ -174,7 +168,7 @@ impl CollabGroup {
/// Task used to receive collab updates from Redis. /// Task used to receive collab updates from Redis.
async fn inbound_task(state: Arc<CollabGroupState>) -> Result<(), RealtimeError> { async fn inbound_task(state: Arc<CollabGroupState>) -> Result<(), RealtimeError> {
let mut updates = state.persister.collab_redis_stream.collab_updates( let updates = state.persister.collab_redis_stream.collab_updates(
&state.workspace_id, &state.workspace_id,
&state.object_id, &state.object_id,
None, None,
@ -233,7 +227,7 @@ impl CollabGroup {
/// Task used to receive awareness updates from Redis. /// Task used to receive awareness updates from Redis.
async fn inbound_awareness_task(state: Arc<CollabGroupState>) -> Result<(), RealtimeError> { async fn inbound_awareness_task(state: Arc<CollabGroupState>) -> Result<(), RealtimeError> {
let mut updates = state.persister.collab_redis_stream.awareness_updates( let updates = state.persister.collab_redis_stream.awareness_updates(
&state.workspace_id, &state.workspace_id,
&state.object_id, &state.object_id,
None, None,
@ -852,6 +846,7 @@ impl Drop for Subscription {
} }
struct CollabPersister { struct CollabPersister {
uid: i64,
workspace_id: String, workspace_id: String,
object_id: String, object_id: String,
collab_type: CollabType, collab_type: CollabType,
@ -868,6 +863,7 @@ impl CollabPersister {
pub const GRACE_PERIOD_MS: u64 = 1000 * 60; // 5min pub const GRACE_PERIOD_MS: u64 = 1000 * 60; // 5min
pub fn new( pub fn new(
uid: i64,
workspace_id: String, workspace_id: String,
object_id: String, object_id: String,
collab_type: CollabType, collab_type: CollabType,
@ -878,6 +874,7 @@ impl CollabPersister {
let update_sink = collab_redis_stream.collab_update_sink(&workspace_id, &object_id); let update_sink = collab_redis_stream.collab_update_sink(&workspace_id, &object_id);
let awareness_sink = collab_redis_stream.awareness_update_sink(&workspace_id, &object_id); let awareness_sink = collab_redis_stream.awareness_update_sink(&workspace_id, &object_id);
Self { Self {
uid,
workspace_id, workspace_id,
object_id, object_id,
collab_type, collab_type,
@ -936,7 +933,7 @@ impl CollabPersister {
// 2. consume all Redis updates on top of it (keep redis msg id) // 2. consume all Redis updates on top of it (keep redis msg id)
let mut last_message_id = None; let mut last_message_id = None;
let mut tx = collab.transact_mut(); let mut tx = collab.transact_mut();
let mut stream = self.collab_redis_stream.collab_updates( let stream = self.collab_redis_stream.collab_updates(
&self.workspace_id, &self.workspace_id,
&self.object_id, &self.object_id,
None, //TODO: store Redis last msg id somewhere in doc state snapshot and replay from there None, //TODO: store Redis last msg id somewhere in doc state snapshot and replay from there
@ -1038,10 +1035,9 @@ impl CollabPersister {
Err(err) => tracing::warn!("failed to fetch embeddings `{}`: {}", self.object_id, err), Err(err) => tracing::warn!("failed to fetch embeddings `{}`: {}", self.object_id, err),
} }
let uid = 0; //FIXME: what UID should go there?
self self
.storage .storage
.insert_or_update_collab(&self.workspace_id, &uid, params, true) .queue_insert_or_update_collab(&self.workspace_id, &self.uid, params, true)
.await .await
.map_err(|err| RealtimeError::Internal(err.into()))?; .map_err(|err| RealtimeError::Internal(err.into()))?;

View File

@ -4,7 +4,7 @@ use std::time::Duration;
use collab::core::collab::DataSource; use collab::core::collab::DataSource;
use collab::core::origin::CollabOrigin; use collab::core::origin::CollabOrigin;
use collab::entity::EncodedCollab; use collab::entity::EncodedCollab;
use collab::lock::{Mutex, RwLock}; use collab::lock::Mutex;
use collab::preclude::Collab; use collab::preclude::Collab;
use collab_entity::CollabType; use collab_entity::CollabType;
use tracing::{error, instrument, trace}; use tracing::{error, instrument, trace};
@ -34,8 +34,6 @@ pub struct GroupManager<S> {
collab_redis_stream: Arc<CollabRedisStream>, collab_redis_stream: Arc<CollabRedisStream>,
control_event_stream: Arc<Mutex<StreamGroup>>, control_event_stream: Arc<Mutex<StreamGroup>>,
persistence_interval: Duration, persistence_interval: Duration,
edit_state_max_count: u32,
edit_state_max_secs: i64,
indexer_provider: Arc<IndexerProvider>, indexer_provider: Arc<IndexerProvider>,
} }
@ -50,8 +48,6 @@ where
metrics_calculate: Arc<CollabRealtimeMetrics>, metrics_calculate: Arc<CollabRealtimeMetrics>,
collab_stream: CollabRedisStream, collab_stream: CollabRedisStream,
persistence_interval: Duration, persistence_interval: Duration,
edit_state_max_count: u32,
edit_state_max_secs: i64,
indexer_provider: Arc<IndexerProvider>, indexer_provider: Arc<IndexerProvider>,
) -> Result<Self, RealtimeError> { ) -> Result<Self, RealtimeError> {
let collab_stream = Arc::new(collab_stream); let collab_stream = Arc::new(collab_stream);
@ -68,8 +64,6 @@ where
collab_redis_stream: collab_stream, collab_redis_stream: collab_stream,
control_event_stream, control_event_stream,
persistence_interval, persistence_interval,
edit_state_max_count,
edit_state_max_secs,
indexer_provider, indexer_provider,
}) })
} }
@ -107,17 +101,18 @@ where
client_msg_router: &mut ClientMessageRouter, client_msg_router: &mut ClientMessageRouter,
) -> Result<(), RealtimeError> { ) -> Result<(), RealtimeError> {
// Lock the group and subscribe the user to the group. // Lock the group and subscribe the user to the group.
if let Some(group) = self.state.get_mut_group(object_id).await { if let Some(mut e) = self.state.get_mut_group(object_id).await {
let group = e.value_mut();
trace!("[realtime]: {} subscribe group:{}", user, object_id,); trace!("[realtime]: {} subscribe group:{}", user, object_id,);
let (sink, stream) = client_msg_router.init_client_communication::<CollabMessage>( let (sink, stream) = client_msg_router.init_client_communication::<CollabMessage>(
&group.workspace_id, group.workspace_id(),
user, user,
object_id, object_id,
self.access_control.clone(), self.access_control.clone(),
); );
group.subscribe(user, message_origin.clone(), sink, stream); group.subscribe(user, message_origin.clone(), sink, stream);
// explicitly drop the group to release the lock. // explicitly drop the group to release the lock.
drop(group); drop(e);
self.state.insert_user(user, object_id).await?; self.state.insert_user(user, object_id).await?;
} else { } else {
@ -160,7 +155,7 @@ where
} }
let result = load_collab(user.uid, object_id, params, self.storage.clone()).await; let result = load_collab(user.uid, object_id, params, self.storage.clone()).await;
let (collab, encode_collab) = { let encode_collab = {
let (mut collab, encode_collab) = match result { let (mut collab, encode_collab) = match result {
Ok(value) => value, Ok(value) => value,
Err(err) => { Err(err) => {
@ -178,8 +173,7 @@ where
}; };
collab.initialize(); collab.initialize();
let collab = Arc::new(RwLock::from(collab)); encode_collab
(collab, encode_collab)
}; };
let cloned_control_event_stream = self.control_event_stream.clone(); let cloned_control_event_stream = self.control_event_stream.clone();

View File

@ -53,8 +53,6 @@ where
command_recv: CLCommandReceiver, command_recv: CLCommandReceiver,
redis_connection_manager: RedisConnectionManager, redis_connection_manager: RedisConnectionManager,
group_persistence_interval: Duration, group_persistence_interval: Duration,
edit_state_max_count: u32,
edit_state_max_secs: i64,
indexer_provider: Arc<IndexerProvider>, indexer_provider: Arc<IndexerProvider>,
) -> Result<Self, RealtimeError> { ) -> Result<Self, RealtimeError> {
let enable_custom_runtime = get_env_var("APPFLOWY_COLLABORATE_MULTI_THREAD", "false") let enable_custom_runtime = get_env_var("APPFLOWY_COLLABORATE_MULTI_THREAD", "false")
@ -76,8 +74,6 @@ where
metrics.clone(), metrics.clone(),
collab_stream, collab_stream,
group_persistence_interval, group_persistence_interval,
edit_state_max_count,
edit_state_max_secs,
indexer_provider.clone(), indexer_provider.clone(),
) )
.await?, .await?,

View File

@ -135,8 +135,6 @@ pub async fn run_actix_server(
rt_cmd_recv, rt_cmd_recv,
state.redis_connection_manager.clone(), state.redis_connection_manager.clone(),
Duration::from_secs(config.collab.group_persistence_interval_secs), Duration::from_secs(config.collab.group_persistence_interval_secs),
config.collab.edit_state_max_count,
config.collab.edit_state_max_secs,
state.indexer_provider.clone(), state.indexer_provider.clone(),
) )
.await .await