mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
send document ping
This commit is contained in:
parent
df5266d7c9
commit
12e8424e8a
@ -19,7 +19,7 @@ use protobuf::Message;
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
#[tracing::instrument(level = "debug", skip(kv_store), err)]
|
#[tracing::instrument(level = "debug", skip(kv_store, params), err)]
|
||||||
pub(crate) async fn create_document(
|
pub(crate) async fn create_document(
|
||||||
kv_store: &Arc<DocumentKVPersistence>,
|
kv_store: &Arc<DocumentKVPersistence>,
|
||||||
mut params: CreateDocParams,
|
mut params: CreateDocParams,
|
||||||
@ -50,7 +50,7 @@ pub async fn reset_document(
|
|||||||
.transaction(|mut transaction| {
|
.transaction(|mut transaction| {
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
let _ = transaction.batch_delete_key_start_with(&doc_id).await?;
|
let _ = transaction.batch_delete_key_start_with(&doc_id).await?;
|
||||||
let items = revisions_to_key_value_items(revisions.into());
|
let items = revisions_to_key_value_items(revisions.into())?;
|
||||||
let _ = transaction.batch_set(items).await?;
|
let _ = transaction.batch_set(items).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
@ -82,7 +82,7 @@ impl DocumentKVPersistence {
|
|||||||
pub(crate) fn new(kv_store: Arc<KVStore>) -> Self { DocumentKVPersistence { inner: kv_store } }
|
pub(crate) fn new(kv_store: Arc<KVStore>) -> Self { DocumentKVPersistence { inner: kv_store } }
|
||||||
|
|
||||||
pub(crate) async fn batch_set_revision(&self, revisions: Vec<Revision>) -> Result<(), ServerError> {
|
pub(crate) async fn batch_set_revision(&self, revisions: Vec<Revision>) -> Result<(), ServerError> {
|
||||||
let items = revisions_to_key_value_items(revisions);
|
let items = revisions_to_key_value_items(revisions)?;
|
||||||
self.inner
|
self.inner
|
||||||
.transaction(|mut t| Box::pin(async move { t.batch_set(items).await }))
|
.transaction(|mut t| Box::pin(async move { t.batch_set(items).await }))
|
||||||
.await
|
.await
|
||||||
@ -152,15 +152,19 @@ impl DocumentKVPersistence {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn revisions_to_key_value_items(revisions: Vec<Revision>) -> Vec<KeyValue> {
|
fn revisions_to_key_value_items(revisions: Vec<Revision>) -> Result<Vec<KeyValue>, ServerError> {
|
||||||
revisions
|
let mut items = vec![];
|
||||||
.into_iter()
|
for revision in revisions {
|
||||||
.map(|revision| {
|
|
||||||
let key = make_revision_key(&revision.doc_id, revision.rev_id);
|
let key = make_revision_key(&revision.doc_id, revision.rev_id);
|
||||||
|
|
||||||
|
if revision.delta_data.is_empty() {
|
||||||
|
return Err(ServerError::internal().context("The delta_data of Revision should not be empty"));
|
||||||
|
}
|
||||||
|
|
||||||
let value = Bytes::from(revision.write_to_bytes().unwrap());
|
let value = Bytes::from(revision.write_to_bytes().unwrap());
|
||||||
KeyValue { key, value }
|
items.push(KeyValue { key, value });
|
||||||
})
|
}
|
||||||
.collect::<Vec<KeyValue>>()
|
Ok(items)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -193,6 +197,11 @@ fn make_doc_from_revisions(doc_id: &str, mut revisions: RepeatedRevision) -> Res
|
|||||||
for revision in revisions {
|
for revision in revisions {
|
||||||
base_rev_id = revision.base_rev_id;
|
base_rev_id = revision.base_rev_id;
|
||||||
rev_id = revision.rev_id;
|
rev_id = revision.rev_id;
|
||||||
|
|
||||||
|
if revision.delta_data.is_empty() {
|
||||||
|
tracing::warn!("revision delta_data is empty");
|
||||||
|
}
|
||||||
|
|
||||||
let delta = RichTextDelta::from_bytes(revision.delta_data).map_err(internal_error)?;
|
let delta = RichTextDelta::from_bytes(revision.delta_data).map_err(internal_error)?;
|
||||||
document_delta = document_delta.compose(&delta).map_err(internal_error)?;
|
document_delta = document_delta.compose(&delta).map_err(internal_error)?;
|
||||||
}
|
}
|
||||||
|
@ -87,17 +87,18 @@ impl DocumentWebSocketActor {
|
|||||||
|
|
||||||
match &document_client_data.ty {
|
match &document_client_data.ty {
|
||||||
DocumentClientWSDataType::ClientPushRev => {
|
DocumentClientWSDataType::ClientPushRev => {
|
||||||
match self
|
let _ = self
|
||||||
.doc_manager
|
.doc_manager
|
||||||
.apply_revisions(user, document_client_data)
|
.handle_client_revisions(user, document_client_data)
|
||||||
.await
|
.await
|
||||||
.map_err(internal_error)
|
.map_err(internal_error)?;
|
||||||
{
|
|
||||||
Ok(_) => {},
|
|
||||||
Err(e) => {
|
|
||||||
tracing::error!("[DocumentWebSocketActor]: process client data failed: {:?}", e);
|
|
||||||
},
|
},
|
||||||
}
|
DocumentClientWSDataType::ClientPing => {
|
||||||
|
let _ = self
|
||||||
|
.doc_manager
|
||||||
|
.handle_client_ping(user, document_client_data)
|
||||||
|
.await
|
||||||
|
.map_err(internal_error)?;
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,22 +2,20 @@
|
|||||||
#![cfg_attr(rustfmt, rustfmt::skip)]
|
#![cfg_attr(rustfmt, rustfmt::skip)]
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use actix_web::web::Data;
|
use actix_web::web::Data;
|
||||||
use flowy_document::services::doc::edit::ClientDocEditor as ClientEditDocContext;
|
use flowy_document::services::doc::edit::ClientDocumentEditor;
|
||||||
use flowy_test::{helper::ViewTest, FlowySDKTest};
|
use flowy_test::{helper::ViewTest, FlowySDKTest};
|
||||||
use flowy_user::services::user::UserSession;
|
use flowy_user::services::user::UserSession;
|
||||||
use futures_util::{stream, stream::StreamExt};
|
use futures_util::{stream, stream::StreamExt};
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use tokio::time::{sleep, Duration};
|
use tokio::time::{sleep, Duration};
|
||||||
// use crate::helper::*;
|
// use crate::helper::*;
|
||||||
use crate::util::helper::{spawn_server, TestServer};
|
use crate::util::helper::{spawn_server, TestServer};
|
||||||
use flowy_collaboration::{entities::doc::DocIdentifier, protobuf::ResetDocumentParams};
|
use flowy_collaboration::{entities::doc::DocumentId, protobuf::ResetDocumentParams};
|
||||||
use lib_ot::rich_text::{RichTextAttribute, RichTextDelta};
|
use lib_ot::rich_text::{RichTextAttribute, RichTextDelta};
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
use backend::services::document::persistence::{DocumentKVPersistence, read_document, reset_document};
|
use backend::services::document::persistence::{DocumentKVPersistence, read_document, reset_document};
|
||||||
|
use flowy_collaboration::entities::revision::{RepeatedRevision, Revision};
|
||||||
use flowy_collaboration::entities::revision::{RepeatedRevision, Revision, RevType};
|
|
||||||
use lib_ot::core::Interval;
|
use lib_ot::core::Interval;
|
||||||
|
|
||||||
use flowy_net::services::ws::FlowyWSConnect;
|
use flowy_net::services::ws::FlowyWSConnect;
|
||||||
@ -56,7 +54,7 @@ impl DocumentTest {
|
|||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct ScriptContext {
|
struct ScriptContext {
|
||||||
client_edit_context: Option<Arc<ClientEditDocContext>>,
|
client_edit_context: Option<Arc<ClientDocumentEditor>>,
|
||||||
client_sdk: FlowySDKTest,
|
client_sdk: FlowySDKTest,
|
||||||
client_user_session: Arc<UserSession>,
|
client_user_session: Arc<UserSession>,
|
||||||
ws_conn: Arc<FlowyWSConnect>,
|
ws_conn: Arc<FlowyWSConnect>,
|
||||||
@ -82,11 +80,11 @@ impl ScriptContext {
|
|||||||
|
|
||||||
async fn open_doc(&mut self) {
|
async fn open_doc(&mut self) {
|
||||||
let doc_id = self.doc_id.clone();
|
let doc_id = self.doc_id.clone();
|
||||||
let edit_context = self.client_sdk.document_ctx.open(DocIdentifier { doc_id }).await.unwrap();
|
let edit_context = self.client_sdk.document_ctx.controller.open(doc_id).await.unwrap();
|
||||||
self.client_edit_context = Some(edit_context);
|
self.client_edit_context = Some(edit_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn client_edit_context(&self) -> Arc<ClientEditDocContext> { self.client_edit_context.as_ref().unwrap().clone() }
|
fn client_edit_context(&self) -> Arc<ClientDocumentEditor> { self.client_edit_context.as_ref().unwrap().clone() }
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn run_scripts(context: Arc<RwLock<ScriptContext>>, scripts: Vec<DocScript>) {
|
async fn run_scripts(context: Arc<RwLock<ScriptContext>>, scripts: Vec<DocScript>) {
|
||||||
@ -126,7 +124,7 @@ async fn run_scripts(context: Arc<RwLock<ScriptContext>>, scripts: Vec<DocScript
|
|||||||
DocScript::AssertServer(s, rev_id) => {
|
DocScript::AssertServer(s, rev_id) => {
|
||||||
sleep(Duration::from_millis(100)).await;
|
sleep(Duration::from_millis(100)).await;
|
||||||
let persistence = Data::new(context.read().server.app_ctx.persistence.kv_store());
|
let persistence = Data::new(context.read().server.app_ctx.persistence.kv_store());
|
||||||
let doc_identifier: flowy_collaboration::protobuf::DocIdentifier = DocIdentifier {
|
let doc_identifier: flowy_collaboration::protobuf::DocumentId = DocumentId {
|
||||||
doc_id
|
doc_id
|
||||||
}.try_into().unwrap();
|
}.try_into().unwrap();
|
||||||
|
|
||||||
@ -144,7 +142,6 @@ async fn run_scripts(context: Arc<RwLock<ScriptContext>>, scripts: Vec<DocScript
|
|||||||
base_rev_id,
|
base_rev_id,
|
||||||
rev_id,
|
rev_id,
|
||||||
delta_data,
|
delta_data,
|
||||||
RevType::Remote,
|
|
||||||
&user_id,
|
&user_id,
|
||||||
md5,
|
md5,
|
||||||
);
|
);
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
// mod edit_script;
|
mod edit_script;
|
||||||
// mod edit_test;
|
mod edit_test;
|
||||||
|
@ -10,11 +10,11 @@ import 'dart:core' as $core;
|
|||||||
import 'package:protobuf/protobuf.dart' as $pb;
|
import 'package:protobuf/protobuf.dart' as $pb;
|
||||||
|
|
||||||
class RevisionState extends $pb.ProtobufEnum {
|
class RevisionState extends $pb.ProtobufEnum {
|
||||||
static const RevisionState StateLocal = RevisionState._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'StateLocal');
|
static const RevisionState Local = RevisionState._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Local');
|
||||||
static const RevisionState Ack = RevisionState._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Ack');
|
static const RevisionState Ack = RevisionState._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Ack');
|
||||||
|
|
||||||
static const $core.List<RevisionState> values = <RevisionState> [
|
static const $core.List<RevisionState> values = <RevisionState> [
|
||||||
StateLocal,
|
Local,
|
||||||
Ack,
|
Ack,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -12,13 +12,13 @@ import 'dart:typed_data' as $typed_data;
|
|||||||
const RevisionState$json = const {
|
const RevisionState$json = const {
|
||||||
'1': 'RevisionState',
|
'1': 'RevisionState',
|
||||||
'2': const [
|
'2': const [
|
||||||
const {'1': 'StateLocal', '2': 0},
|
const {'1': 'Local', '2': 0},
|
||||||
const {'1': 'Ack', '2': 1},
|
const {'1': 'Ack', '2': 1},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Descriptor for `RevisionState`. Decode as a `google.protobuf.EnumDescriptorProto`.
|
/// Descriptor for `RevisionState`. Decode as a `google.protobuf.EnumDescriptorProto`.
|
||||||
final $typed_data.Uint8List revisionStateDescriptor = $convert.base64Decode('Cg1SZXZpc2lvblN0YXRlEg4KClN0YXRlTG9jYWwQABIHCgNBY2sQAQ==');
|
final $typed_data.Uint8List revisionStateDescriptor = $convert.base64Decode('Cg1SZXZpc2lvblN0YXRlEgkKBUxvY2FsEAASBwoDQWNrEAE=');
|
||||||
@$core.Deprecated('Use revTypeDescriptor instead')
|
@$core.Deprecated('Use revTypeDescriptor instead')
|
||||||
const RevType$json = const {
|
const RevType$json = const {
|
||||||
'1': 'RevType',
|
'1': 'RevType',
|
||||||
|
@ -11,9 +11,11 @@ import 'package:protobuf/protobuf.dart' as $pb;
|
|||||||
|
|
||||||
class DocumentClientWSDataType extends $pb.ProtobufEnum {
|
class DocumentClientWSDataType extends $pb.ProtobufEnum {
|
||||||
static const DocumentClientWSDataType ClientPushRev = DocumentClientWSDataType._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ClientPushRev');
|
static const DocumentClientWSDataType ClientPushRev = DocumentClientWSDataType._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ClientPushRev');
|
||||||
|
static const DocumentClientWSDataType ClientPing = DocumentClientWSDataType._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ClientPing');
|
||||||
|
|
||||||
static const $core.List<DocumentClientWSDataType> values = <DocumentClientWSDataType> [
|
static const $core.List<DocumentClientWSDataType> values = <DocumentClientWSDataType> [
|
||||||
ClientPushRev,
|
ClientPushRev,
|
||||||
|
ClientPing,
|
||||||
];
|
];
|
||||||
|
|
||||||
static final $core.Map<$core.int, DocumentClientWSDataType> _byValue = $pb.ProtobufEnum.initByValue(values);
|
static final $core.Map<$core.int, DocumentClientWSDataType> _byValue = $pb.ProtobufEnum.initByValue(values);
|
||||||
|
@ -13,11 +13,12 @@ const DocumentClientWSDataType$json = const {
|
|||||||
'1': 'DocumentClientWSDataType',
|
'1': 'DocumentClientWSDataType',
|
||||||
'2': const [
|
'2': const [
|
||||||
const {'1': 'ClientPushRev', '2': 0},
|
const {'1': 'ClientPushRev', '2': 0},
|
||||||
|
const {'1': 'ClientPing', '2': 1},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Descriptor for `DocumentClientWSDataType`. Decode as a `google.protobuf.EnumDescriptorProto`.
|
/// Descriptor for `DocumentClientWSDataType`. Decode as a `google.protobuf.EnumDescriptorProto`.
|
||||||
final $typed_data.Uint8List documentClientWSDataTypeDescriptor = $convert.base64Decode('ChhEb2N1bWVudENsaWVudFdTRGF0YVR5cGUSEQoNQ2xpZW50UHVzaFJldhAA');
|
final $typed_data.Uint8List documentClientWSDataTypeDescriptor = $convert.base64Decode('ChhEb2N1bWVudENsaWVudFdTRGF0YVR5cGUSEQoNQ2xpZW50UHVzaFJldhAAEg4KCkNsaWVudFBpbmcQAQ==');
|
||||||
@$core.Deprecated('Use documentServerWSDataTypeDescriptor instead')
|
@$core.Deprecated('Use documentServerWSDataTypeDescriptor instead')
|
||||||
const DocumentServerWSDataType$json = const {
|
const DocumentServerWSDataType$json = const {
|
||||||
'1': 'DocumentServerWSDataType',
|
'1': 'DocumentServerWSDataType',
|
||||||
|
@ -688,6 +688,13 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.12.11"
|
version: "0.12.11"
|
||||||
|
material_color_utilities:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: material_color_utilities
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.1.2"
|
||||||
meta:
|
meta:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1077,7 +1084,7 @@ packages:
|
|||||||
name: test_api
|
name: test_api
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.4.3"
|
version: "0.4.8"
|
||||||
textstyle_extensions:
|
textstyle_extensions:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -62,8 +62,8 @@ impl ViewController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(level = "debug", skip(self, params), fields(name = %params.name), err)]
|
#[tracing::instrument(level = "debug", skip(self, params), fields(name = %params.name), err)]
|
||||||
pub(crate) async fn create_view_from_params(&self, mut params: CreateViewParams) -> Result<View, FlowyError> {
|
pub(crate) async fn create_view_from_params(&self, params: CreateViewParams) -> Result<View, FlowyError> {
|
||||||
let delta_data = Bytes::from(params.take_view_data());
|
let delta_data = Bytes::from(params.view_data.clone());
|
||||||
let user_id = self.user.user_id()?;
|
let user_id = self.user.user_id()?;
|
||||||
let repeated_revision: RepeatedRevision =
|
let repeated_revision: RepeatedRevision =
|
||||||
Revision::initial_revision(&user_id, ¶ms.view_id, delta_data).into();
|
Revision::initial_revision(&user_id, ¶ms.view_id, delta_data).into();
|
||||||
|
@ -26,7 +26,7 @@ pub trait RevisionServer: Send + Sync {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct RevisionManager {
|
pub struct RevisionManager {
|
||||||
doc_id: String,
|
pub(crate) doc_id: String,
|
||||||
user_id: String,
|
user_id: String,
|
||||||
rev_id_counter: RevIdCounter,
|
rev_id_counter: RevIdCounter,
|
||||||
cache: Arc<RevisionCache>,
|
cache: Arc<RevisionCache>,
|
||||||
@ -67,6 +67,9 @@ impl RevisionManager {
|
|||||||
|
|
||||||
#[tracing::instrument(level = "debug", skip(self, revision))]
|
#[tracing::instrument(level = "debug", skip(self, revision))]
|
||||||
pub async fn add_remote_revision(&self, revision: &Revision) -> Result<(), FlowyError> {
|
pub async fn add_remote_revision(&self, revision: &Revision) -> Result<(), FlowyError> {
|
||||||
|
if revision.delta_data.is_empty() {
|
||||||
|
return Err(FlowyError::internal().context("Delta data should be empty"));
|
||||||
|
}
|
||||||
self.rev_id_counter.set(revision.rev_id);
|
self.rev_id_counter.set(revision.rev_id);
|
||||||
let _ = self.cache.add(revision.clone(), RevisionState::Ack, true).await?;
|
let _ = self.cache.add(revision.clone(), RevisionState::Ack, true).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -74,6 +77,10 @@ impl RevisionManager {
|
|||||||
|
|
||||||
#[tracing::instrument(level = "debug", skip(self, revision))]
|
#[tracing::instrument(level = "debug", skip(self, revision))]
|
||||||
pub async fn add_local_revision(&self, revision: &Revision) -> Result<(), FlowyError> {
|
pub async fn add_local_revision(&self, revision: &Revision) -> Result<(), FlowyError> {
|
||||||
|
if revision.delta_data.is_empty() {
|
||||||
|
return Err(FlowyError::internal().context("Delta data should be empty"));
|
||||||
|
}
|
||||||
|
|
||||||
let record = self.cache.add(revision.clone(), RevisionState::Local, true).await?;
|
let record = self.cache.add(revision.clone(), RevisionState::Local, true).await?;
|
||||||
self.sync_seq.add_revision(record).await?;
|
self.sync_seq.add_revision(record).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -285,7 +285,12 @@ impl SharedWSSinkDataProvider {
|
|||||||
let doc_id = rev.doc_id.clone();
|
let doc_id = rev.doc_id.clone();
|
||||||
Ok(Some(DocumentClientWSData::from_revisions(&doc_id, vec![rev])))
|
Ok(Some(DocumentClientWSData::from_revisions(&doc_id, vec![rev])))
|
||||||
},
|
},
|
||||||
None => Ok(None),
|
None => {
|
||||||
|
//
|
||||||
|
let doc_id = self.rev_manager.doc_id.clone();
|
||||||
|
let latest_rev_id = self.rev_manager.rev_id();
|
||||||
|
Ok(Some(DocumentClientWSData::ping(&doc_id, latest_rev_id)))
|
||||||
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -37,9 +37,15 @@ impl MockDocServer {
|
|||||||
});
|
});
|
||||||
let pb_client_data: flowy_collaboration::protobuf::DocumentClientWSData =
|
let pb_client_data: flowy_collaboration::protobuf::DocumentClientWSData =
|
||||||
client_data.try_into().unwrap();
|
client_data.try_into().unwrap();
|
||||||
self.manager.apply_revisions(user, pb_client_data).await.unwrap();
|
self.manager
|
||||||
|
.handle_client_revisions(user, pb_client_data)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
Some(rx)
|
Some(rx)
|
||||||
},
|
},
|
||||||
|
DocumentClientWSDataType::ClientPing => {
|
||||||
|
todo!()
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -117,6 +117,8 @@ impl RepeatedRevision {
|
|||||||
Self { items }
|
Self { items }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn empty() -> Self { RepeatedRevision { items: vec![] } }
|
||||||
|
|
||||||
pub fn into_inner(self) -> Vec<Revision> { self.items }
|
pub fn into_inner(self) -> Vec<Revision> { self.items }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ use std::convert::{TryFrom, TryInto};
|
|||||||
#[derive(Debug, Clone, ProtoBuf_Enum, Eq, PartialEq, Hash)]
|
#[derive(Debug, Clone, ProtoBuf_Enum, Eq, PartialEq, Hash)]
|
||||||
pub enum DocumentClientWSDataType {
|
pub enum DocumentClientWSDataType {
|
||||||
ClientPushRev = 0,
|
ClientPushRev = 0,
|
||||||
|
ClientPing = 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DocumentClientWSDataType {
|
impl DocumentClientWSDataType {
|
||||||
@ -54,6 +55,15 @@ impl DocumentClientWSData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn ping(doc_id: &str, rev_id: i64) -> Self {
|
||||||
|
Self {
|
||||||
|
doc_id: doc_id.to_owned(),
|
||||||
|
ty: DocumentClientWSDataType::ClientPing,
|
||||||
|
revisions: RepeatedRevision::empty(),
|
||||||
|
id: rev_id.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn id(&self) -> String { self.id.clone() }
|
pub fn id(&self) -> String { self.id.clone() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -958,7 +958,7 @@ impl ::protobuf::reflect::ProtobufValue for RevisionRange {
|
|||||||
|
|
||||||
#[derive(Clone,PartialEq,Eq,Debug,Hash)]
|
#[derive(Clone,PartialEq,Eq,Debug,Hash)]
|
||||||
pub enum RevisionState {
|
pub enum RevisionState {
|
||||||
StateLocal = 0,
|
Local = 0,
|
||||||
Ack = 1,
|
Ack = 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -969,7 +969,7 @@ impl ::protobuf::ProtobufEnum for RevisionState {
|
|||||||
|
|
||||||
fn from_i32(value: i32) -> ::std::option::Option<RevisionState> {
|
fn from_i32(value: i32) -> ::std::option::Option<RevisionState> {
|
||||||
match value {
|
match value {
|
||||||
0 => ::std::option::Option::Some(RevisionState::StateLocal),
|
0 => ::std::option::Option::Some(RevisionState::Local),
|
||||||
1 => ::std::option::Option::Some(RevisionState::Ack),
|
1 => ::std::option::Option::Some(RevisionState::Ack),
|
||||||
_ => ::std::option::Option::None
|
_ => ::std::option::Option::None
|
||||||
}
|
}
|
||||||
@ -977,7 +977,7 @@ impl ::protobuf::ProtobufEnum for RevisionState {
|
|||||||
|
|
||||||
fn values() -> &'static [Self] {
|
fn values() -> &'static [Self] {
|
||||||
static values: &'static [RevisionState] = &[
|
static values: &'static [RevisionState] = &[
|
||||||
RevisionState::StateLocal,
|
RevisionState::Local,
|
||||||
RevisionState::Ack,
|
RevisionState::Ack,
|
||||||
];
|
];
|
||||||
values
|
values
|
||||||
@ -996,7 +996,7 @@ impl ::std::marker::Copy for RevisionState {
|
|||||||
|
|
||||||
impl ::std::default::Default for RevisionState {
|
impl ::std::default::Default for RevisionState {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
RevisionState::StateLocal
|
RevisionState::Local
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1067,8 +1067,8 @@ static file_descriptor_proto_data: &'static [u8] = b"\
|
|||||||
\"\x1d\n\x05RevId\x12\x14\n\x05value\x18\x01\x20\x01(\x03R\x05value\"N\n\
|
\"\x1d\n\x05RevId\x12\x14\n\x05value\x18\x01\x20\x01(\x03R\x05value\"N\n\
|
||||||
\rRevisionRange\x12\x15\n\x06doc_id\x18\x01\x20\x01(\tR\x05docId\x12\x14\
|
\rRevisionRange\x12\x15\n\x06doc_id\x18\x01\x20\x01(\tR\x05docId\x12\x14\
|
||||||
\n\x05start\x18\x02\x20\x01(\x03R\x05start\x12\x10\n\x03end\x18\x03\x20\
|
\n\x05start\x18\x02\x20\x01(\x03R\x05start\x12\x10\n\x03end\x18\x03\x20\
|
||||||
\x01(\x03R\x03end*(\n\rRevisionState\x12\x0e\n\nStateLocal\x10\0\x12\x07\
|
\x01(\x03R\x03end*#\n\rRevisionState\x12\t\n\x05Local\x10\0\x12\x07\n\
|
||||||
\n\x03Ack\x10\x01*4\n\x07RevType\x12\x13\n\x0fDeprecatedLocal\x10\0\x12\
|
\x03Ack\x10\x01*4\n\x07RevType\x12\x13\n\x0fDeprecatedLocal\x10\0\x12\
|
||||||
\x14\n\x10DeprecatedRemote\x10\x01J\xe8\x07\n\x06\x12\x04\0\0\x1d\x01\n\
|
\x14\n\x10DeprecatedRemote\x10\x01J\xe8\x07\n\x06\x12\x04\0\0\x1d\x01\n\
|
||||||
\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\x04\0\x12\x04\x02\0\n\x01\n\n\n\
|
\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\x04\0\x12\x04\x02\0\n\x01\n\n\n\
|
||||||
\x03\x04\0\x01\x12\x03\x02\x08\x10\n\x0b\n\x04\x04\0\x02\0\x12\x03\x03\
|
\x03\x04\0\x01\x12\x03\x02\x08\x10\n\x0b\n\x04\x04\0\x02\0\x12\x03\x03\
|
||||||
@ -1109,16 +1109,16 @@ static file_descriptor_proto_data: &'static [u8] = b"\
|
|||||||
\n\x0c\n\x05\x04\x03\x02\x02\x05\x12\x03\x14\x04\t\n\x0c\n\x05\x04\x03\
|
\n\x0c\n\x05\x04\x03\x02\x02\x05\x12\x03\x14\x04\t\n\x0c\n\x05\x04\x03\
|
||||||
\x02\x02\x01\x12\x03\x14\n\r\n\x0c\n\x05\x04\x03\x02\x02\x03\x12\x03\x14\
|
\x02\x02\x01\x12\x03\x14\n\r\n\x0c\n\x05\x04\x03\x02\x02\x03\x12\x03\x14\
|
||||||
\x10\x11\n\n\n\x02\x05\0\x12\x04\x16\0\x19\x01\n\n\n\x03\x05\0\x01\x12\
|
\x10\x11\n\n\n\x02\x05\0\x12\x04\x16\0\x19\x01\n\n\n\x03\x05\0\x01\x12\
|
||||||
\x03\x16\x05\x12\n\x0b\n\x04\x05\0\x02\0\x12\x03\x17\x04\x13\n\x0c\n\x05\
|
\x03\x16\x05\x12\n\x0b\n\x04\x05\0\x02\0\x12\x03\x17\x04\x0e\n\x0c\n\x05\
|
||||||
\x05\0\x02\0\x01\x12\x03\x17\x04\x0e\n\x0c\n\x05\x05\0\x02\0\x02\x12\x03\
|
\x05\0\x02\0\x01\x12\x03\x17\x04\t\n\x0c\n\x05\x05\0\x02\0\x02\x12\x03\
|
||||||
\x17\x11\x12\n\x0b\n\x04\x05\0\x02\x01\x12\x03\x18\x04\x0c\n\x0c\n\x05\
|
\x17\x0c\r\n\x0b\n\x04\x05\0\x02\x01\x12\x03\x18\x04\x0c\n\x0c\n\x05\x05\
|
||||||
\x05\0\x02\x01\x01\x12\x03\x18\x04\x07\n\x0c\n\x05\x05\0\x02\x01\x02\x12\
|
\0\x02\x01\x01\x12\x03\x18\x04\x07\n\x0c\n\x05\x05\0\x02\x01\x02\x12\x03\
|
||||||
\x03\x18\n\x0b\n\n\n\x02\x05\x01\x12\x04\x1a\0\x1d\x01\n\n\n\x03\x05\x01\
|
\x18\n\x0b\n\n\n\x02\x05\x01\x12\x04\x1a\0\x1d\x01\n\n\n\x03\x05\x01\x01\
|
||||||
\x01\x12\x03\x1a\x05\x0c\n\x0b\n\x04\x05\x01\x02\0\x12\x03\x1b\x04\x18\n\
|
\x12\x03\x1a\x05\x0c\n\x0b\n\x04\x05\x01\x02\0\x12\x03\x1b\x04\x18\n\x0c\
|
||||||
\x0c\n\x05\x05\x01\x02\0\x01\x12\x03\x1b\x04\x13\n\x0c\n\x05\x05\x01\x02\
|
\n\x05\x05\x01\x02\0\x01\x12\x03\x1b\x04\x13\n\x0c\n\x05\x05\x01\x02\0\
|
||||||
\0\x02\x12\x03\x1b\x16\x17\n\x0b\n\x04\x05\x01\x02\x01\x12\x03\x1c\x04\
|
\x02\x12\x03\x1b\x16\x17\n\x0b\n\x04\x05\x01\x02\x01\x12\x03\x1c\x04\x19\
|
||||||
\x19\n\x0c\n\x05\x05\x01\x02\x01\x01\x12\x03\x1c\x04\x14\n\x0c\n\x05\x05\
|
\n\x0c\n\x05\x05\x01\x02\x01\x01\x12\x03\x1c\x04\x14\n\x0c\n\x05\x05\x01\
|
||||||
\x01\x02\x01\x02\x12\x03\x1c\x17\x18b\x06proto3\
|
\x02\x01\x02\x12\x03\x1c\x17\x18b\x06proto3\
|
||||||
";
|
";
|
||||||
|
|
||||||
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;
|
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;
|
||||||
|
@ -790,6 +790,7 @@ impl ::protobuf::reflect::ProtobufValue for NewDocumentUser {
|
|||||||
#[derive(Clone,PartialEq,Eq,Debug,Hash)]
|
#[derive(Clone,PartialEq,Eq,Debug,Hash)]
|
||||||
pub enum DocumentClientWSDataType {
|
pub enum DocumentClientWSDataType {
|
||||||
ClientPushRev = 0,
|
ClientPushRev = 0,
|
||||||
|
ClientPing = 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ::protobuf::ProtobufEnum for DocumentClientWSDataType {
|
impl ::protobuf::ProtobufEnum for DocumentClientWSDataType {
|
||||||
@ -800,6 +801,7 @@ impl ::protobuf::ProtobufEnum for DocumentClientWSDataType {
|
|||||||
fn from_i32(value: i32) -> ::std::option::Option<DocumentClientWSDataType> {
|
fn from_i32(value: i32) -> ::std::option::Option<DocumentClientWSDataType> {
|
||||||
match value {
|
match value {
|
||||||
0 => ::std::option::Option::Some(DocumentClientWSDataType::ClientPushRev),
|
0 => ::std::option::Option::Some(DocumentClientWSDataType::ClientPushRev),
|
||||||
|
1 => ::std::option::Option::Some(DocumentClientWSDataType::ClientPing),
|
||||||
_ => ::std::option::Option::None
|
_ => ::std::option::Option::None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -807,6 +809,7 @@ impl ::protobuf::ProtobufEnum for DocumentClientWSDataType {
|
|||||||
fn values() -> &'static [Self] {
|
fn values() -> &'static [Self] {
|
||||||
static values: &'static [DocumentClientWSDataType] = &[
|
static values: &'static [DocumentClientWSDataType] = &[
|
||||||
DocumentClientWSDataType::ClientPushRev,
|
DocumentClientWSDataType::ClientPushRev,
|
||||||
|
DocumentClientWSDataType::ClientPing,
|
||||||
];
|
];
|
||||||
values
|
values
|
||||||
}
|
}
|
||||||
@ -900,55 +903,57 @@ static file_descriptor_proto_data: &'static [u8] = b"\
|
|||||||
umentServerWSDataTypeR\x02ty\x12\x12\n\x04data\x18\x03\x20\x01(\x0cR\x04\
|
umentServerWSDataTypeR\x02ty\x12\x12\n\x04data\x18\x03\x20\x01(\x0cR\x04\
|
||||||
data\"f\n\x0fNewDocumentUser\x12\x17\n\x07user_id\x18\x01\x20\x01(\tR\
|
data\"f\n\x0fNewDocumentUser\x12\x17\n\x07user_id\x18\x01\x20\x01(\tR\
|
||||||
\x06userId\x12\x15\n\x06doc_id\x18\x02\x20\x01(\tR\x05docId\x12#\n\rrevi\
|
\x06userId\x12\x15\n\x06doc_id\x18\x02\x20\x01(\tR\x05docId\x12#\n\rrevi\
|
||||||
sion_data\x18\x03\x20\x01(\x0cR\x0crevisionData*-\n\x18DocumentClientWSD\
|
sion_data\x18\x03\x20\x01(\x0cR\x0crevisionData*=\n\x18DocumentClientWSD\
|
||||||
ataType\x12\x11\n\rClientPushRev\x10\0*`\n\x18DocumentServerWSDataType\
|
ataType\x12\x11\n\rClientPushRev\x10\0\x12\x0e\n\nClientPing\x10\x01*`\n\
|
||||||
\x12\r\n\tServerAck\x10\0\x12\x11\n\rServerPushRev\x10\x01\x12\x11\n\rSe\
|
\x18DocumentServerWSDataType\x12\r\n\tServerAck\x10\0\x12\x11\n\rServerP\
|
||||||
rverPullRev\x10\x02\x12\x0f\n\x0bUserConnect\x10\x03J\x88\x07\n\x06\x12\
|
ushRev\x10\x01\x12\x11\n\rServerPullRev\x10\x02\x12\x0f\n\x0bUserConnect\
|
||||||
\x04\0\0\x1b\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\t\n\x02\x03\0\x12\x03\
|
\x10\x03J\xb1\x07\n\x06\x12\x04\0\0\x1c\x01\n\x08\n\x01\x0c\x12\x03\0\0\
|
||||||
\x01\0\x18\n\n\n\x02\x04\0\x12\x04\x03\0\x08\x01\n\n\n\x03\x04\0\x01\x12\
|
\x12\n\t\n\x02\x03\0\x12\x03\x01\0\x18\n\n\n\x02\x04\0\x12\x04\x03\0\x08\
|
||||||
\x03\x03\x08\x1c\n\x0b\n\x04\x04\0\x02\0\x12\x03\x04\x04\x16\n\x0c\n\x05\
|
\x01\n\n\n\x03\x04\0\x01\x12\x03\x03\x08\x1c\n\x0b\n\x04\x04\0\x02\0\x12\
|
||||||
\x04\0\x02\0\x05\x12\x03\x04\x04\n\n\x0c\n\x05\x04\0\x02\0\x01\x12\x03\
|
\x03\x04\x04\x16\n\x0c\n\x05\x04\0\x02\0\x05\x12\x03\x04\x04\n\n\x0c\n\
|
||||||
\x04\x0b\x11\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x04\x14\x15\n\x0b\n\x04\
|
\x05\x04\0\x02\0\x01\x12\x03\x04\x0b\x11\n\x0c\n\x05\x04\0\x02\0\x03\x12\
|
||||||
\x04\0\x02\x01\x12\x03\x05\x04$\n\x0c\n\x05\x04\0\x02\x01\x06\x12\x03\
|
\x03\x04\x14\x15\n\x0b\n\x04\x04\0\x02\x01\x12\x03\x05\x04$\n\x0c\n\x05\
|
||||||
\x05\x04\x1c\n\x0c\n\x05\x04\0\x02\x01\x01\x12\x03\x05\x1d\x1f\n\x0c\n\
|
\x04\0\x02\x01\x06\x12\x03\x05\x04\x1c\n\x0c\n\x05\x04\0\x02\x01\x01\x12\
|
||||||
\x05\x04\0\x02\x01\x03\x12\x03\x05\"#\n\x0b\n\x04\x04\0\x02\x02\x12\x03\
|
\x03\x05\x1d\x1f\n\x0c\n\x05\x04\0\x02\x01\x03\x12\x03\x05\"#\n\x0b\n\
|
||||||
\x06\x04#\n\x0c\n\x05\x04\0\x02\x02\x06\x12\x03\x06\x04\x14\n\x0c\n\x05\
|
\x04\x04\0\x02\x02\x12\x03\x06\x04#\n\x0c\n\x05\x04\0\x02\x02\x06\x12\
|
||||||
\x04\0\x02\x02\x01\x12\x03\x06\x15\x1e\n\x0c\n\x05\x04\0\x02\x02\x03\x12\
|
\x03\x06\x04\x14\n\x0c\n\x05\x04\0\x02\x02\x01\x12\x03\x06\x15\x1e\n\x0c\
|
||||||
\x03\x06!\"\n\x0b\n\x04\x04\0\x02\x03\x12\x03\x07\x04\x12\n\x0c\n\x05\
|
\n\x05\x04\0\x02\x02\x03\x12\x03\x06!\"\n\x0b\n\x04\x04\0\x02\x03\x12\
|
||||||
\x04\0\x02\x03\x05\x12\x03\x07\x04\n\n\x0c\n\x05\x04\0\x02\x03\x01\x12\
|
\x03\x07\x04\x12\n\x0c\n\x05\x04\0\x02\x03\x05\x12\x03\x07\x04\n\n\x0c\n\
|
||||||
\x03\x07\x0b\r\n\x0c\n\x05\x04\0\x02\x03\x03\x12\x03\x07\x10\x11\n\n\n\
|
\x05\x04\0\x02\x03\x01\x12\x03\x07\x0b\r\n\x0c\n\x05\x04\0\x02\x03\x03\
|
||||||
\x02\x04\x01\x12\x04\t\0\r\x01\n\n\n\x03\x04\x01\x01\x12\x03\t\x08\x1c\n\
|
\x12\x03\x07\x10\x11\n\n\n\x02\x04\x01\x12\x04\t\0\r\x01\n\n\n\x03\x04\
|
||||||
\x0b\n\x04\x04\x01\x02\0\x12\x03\n\x04\x16\n\x0c\n\x05\x04\x01\x02\0\x05\
|
\x01\x01\x12\x03\t\x08\x1c\n\x0b\n\x04\x04\x01\x02\0\x12\x03\n\x04\x16\n\
|
||||||
\x12\x03\n\x04\n\n\x0c\n\x05\x04\x01\x02\0\x01\x12\x03\n\x0b\x11\n\x0c\n\
|
\x0c\n\x05\x04\x01\x02\0\x05\x12\x03\n\x04\n\n\x0c\n\x05\x04\x01\x02\0\
|
||||||
\x05\x04\x01\x02\0\x03\x12\x03\n\x14\x15\n\x0b\n\x04\x04\x01\x02\x01\x12\
|
\x01\x12\x03\n\x0b\x11\n\x0c\n\x05\x04\x01\x02\0\x03\x12\x03\n\x14\x15\n\
|
||||||
\x03\x0b\x04$\n\x0c\n\x05\x04\x01\x02\x01\x06\x12\x03\x0b\x04\x1c\n\x0c\
|
\x0b\n\x04\x04\x01\x02\x01\x12\x03\x0b\x04$\n\x0c\n\x05\x04\x01\x02\x01\
|
||||||
\n\x05\x04\x01\x02\x01\x01\x12\x03\x0b\x1d\x1f\n\x0c\n\x05\x04\x01\x02\
|
\x06\x12\x03\x0b\x04\x1c\n\x0c\n\x05\x04\x01\x02\x01\x01\x12\x03\x0b\x1d\
|
||||||
\x01\x03\x12\x03\x0b\"#\n\x0b\n\x04\x04\x01\x02\x02\x12\x03\x0c\x04\x13\
|
\x1f\n\x0c\n\x05\x04\x01\x02\x01\x03\x12\x03\x0b\"#\n\x0b\n\x04\x04\x01\
|
||||||
\n\x0c\n\x05\x04\x01\x02\x02\x05\x12\x03\x0c\x04\t\n\x0c\n\x05\x04\x01\
|
\x02\x02\x12\x03\x0c\x04\x13\n\x0c\n\x05\x04\x01\x02\x02\x05\x12\x03\x0c\
|
||||||
\x02\x02\x01\x12\x03\x0c\n\x0e\n\x0c\n\x05\x04\x01\x02\x02\x03\x12\x03\
|
\x04\t\n\x0c\n\x05\x04\x01\x02\x02\x01\x12\x03\x0c\n\x0e\n\x0c\n\x05\x04\
|
||||||
\x0c\x11\x12\n\n\n\x02\x04\x02\x12\x04\x0e\0\x12\x01\n\n\n\x03\x04\x02\
|
\x01\x02\x02\x03\x12\x03\x0c\x11\x12\n\n\n\x02\x04\x02\x12\x04\x0e\0\x12\
|
||||||
\x01\x12\x03\x0e\x08\x17\n\x0b\n\x04\x04\x02\x02\0\x12\x03\x0f\x04\x17\n\
|
\x01\n\n\n\x03\x04\x02\x01\x12\x03\x0e\x08\x17\n\x0b\n\x04\x04\x02\x02\0\
|
||||||
\x0c\n\x05\x04\x02\x02\0\x05\x12\x03\x0f\x04\n\n\x0c\n\x05\x04\x02\x02\0\
|
\x12\x03\x0f\x04\x17\n\x0c\n\x05\x04\x02\x02\0\x05\x12\x03\x0f\x04\n\n\
|
||||||
\x01\x12\x03\x0f\x0b\x12\n\x0c\n\x05\x04\x02\x02\0\x03\x12\x03\x0f\x15\
|
\x0c\n\x05\x04\x02\x02\0\x01\x12\x03\x0f\x0b\x12\n\x0c\n\x05\x04\x02\x02\
|
||||||
\x16\n\x0b\n\x04\x04\x02\x02\x01\x12\x03\x10\x04\x16\n\x0c\n\x05\x04\x02\
|
\0\x03\x12\x03\x0f\x15\x16\n\x0b\n\x04\x04\x02\x02\x01\x12\x03\x10\x04\
|
||||||
\x02\x01\x05\x12\x03\x10\x04\n\n\x0c\n\x05\x04\x02\x02\x01\x01\x12\x03\
|
\x16\n\x0c\n\x05\x04\x02\x02\x01\x05\x12\x03\x10\x04\n\n\x0c\n\x05\x04\
|
||||||
\x10\x0b\x11\n\x0c\n\x05\x04\x02\x02\x01\x03\x12\x03\x10\x14\x15\n\x0b\n\
|
\x02\x02\x01\x01\x12\x03\x10\x0b\x11\n\x0c\n\x05\x04\x02\x02\x01\x03\x12\
|
||||||
\x04\x04\x02\x02\x02\x12\x03\x11\x04\x1c\n\x0c\n\x05\x04\x02\x02\x02\x05\
|
\x03\x10\x14\x15\n\x0b\n\x04\x04\x02\x02\x02\x12\x03\x11\x04\x1c\n\x0c\n\
|
||||||
\x12\x03\x11\x04\t\n\x0c\n\x05\x04\x02\x02\x02\x01\x12\x03\x11\n\x17\n\
|
\x05\x04\x02\x02\x02\x05\x12\x03\x11\x04\t\n\x0c\n\x05\x04\x02\x02\x02\
|
||||||
\x0c\n\x05\x04\x02\x02\x02\x03\x12\x03\x11\x1a\x1b\n\n\n\x02\x05\0\x12\
|
\x01\x12\x03\x11\n\x17\n\x0c\n\x05\x04\x02\x02\x02\x03\x12\x03\x11\x1a\
|
||||||
\x04\x13\0\x15\x01\n\n\n\x03\x05\0\x01\x12\x03\x13\x05\x1d\n\x0b\n\x04\
|
\x1b\n\n\n\x02\x05\0\x12\x04\x13\0\x16\x01\n\n\n\x03\x05\0\x01\x12\x03\
|
||||||
\x05\0\x02\0\x12\x03\x14\x04\x16\n\x0c\n\x05\x05\0\x02\0\x01\x12\x03\x14\
|
\x13\x05\x1d\n\x0b\n\x04\x05\0\x02\0\x12\x03\x14\x04\x16\n\x0c\n\x05\x05\
|
||||||
\x04\x11\n\x0c\n\x05\x05\0\x02\0\x02\x12\x03\x14\x14\x15\n\n\n\x02\x05\
|
\0\x02\0\x01\x12\x03\x14\x04\x11\n\x0c\n\x05\x05\0\x02\0\x02\x12\x03\x14\
|
||||||
\x01\x12\x04\x16\0\x1b\x01\n\n\n\x03\x05\x01\x01\x12\x03\x16\x05\x1d\n\
|
\x14\x15\n\x0b\n\x04\x05\0\x02\x01\x12\x03\x15\x04\x13\n\x0c\n\x05\x05\0\
|
||||||
\x0b\n\x04\x05\x01\x02\0\x12\x03\x17\x04\x12\n\x0c\n\x05\x05\x01\x02\0\
|
\x02\x01\x01\x12\x03\x15\x04\x0e\n\x0c\n\x05\x05\0\x02\x01\x02\x12\x03\
|
||||||
\x01\x12\x03\x17\x04\r\n\x0c\n\x05\x05\x01\x02\0\x02\x12\x03\x17\x10\x11\
|
\x15\x11\x12\n\n\n\x02\x05\x01\x12\x04\x17\0\x1c\x01\n\n\n\x03\x05\x01\
|
||||||
\n\x0b\n\x04\x05\x01\x02\x01\x12\x03\x18\x04\x16\n\x0c\n\x05\x05\x01\x02\
|
\x01\x12\x03\x17\x05\x1d\n\x0b\n\x04\x05\x01\x02\0\x12\x03\x18\x04\x12\n\
|
||||||
\x01\x01\x12\x03\x18\x04\x11\n\x0c\n\x05\x05\x01\x02\x01\x02\x12\x03\x18\
|
\x0c\n\x05\x05\x01\x02\0\x01\x12\x03\x18\x04\r\n\x0c\n\x05\x05\x01\x02\0\
|
||||||
\x14\x15\n\x0b\n\x04\x05\x01\x02\x02\x12\x03\x19\x04\x16\n\x0c\n\x05\x05\
|
\x02\x12\x03\x18\x10\x11\n\x0b\n\x04\x05\x01\x02\x01\x12\x03\x19\x04\x16\
|
||||||
\x01\x02\x02\x01\x12\x03\x19\x04\x11\n\x0c\n\x05\x05\x01\x02\x02\x02\x12\
|
\n\x0c\n\x05\x05\x01\x02\x01\x01\x12\x03\x19\x04\x11\n\x0c\n\x05\x05\x01\
|
||||||
\x03\x19\x14\x15\n\x0b\n\x04\x05\x01\x02\x03\x12\x03\x1a\x04\x14\n\x0c\n\
|
\x02\x01\x02\x12\x03\x19\x14\x15\n\x0b\n\x04\x05\x01\x02\x02\x12\x03\x1a\
|
||||||
\x05\x05\x01\x02\x03\x01\x12\x03\x1a\x04\x0f\n\x0c\n\x05\x05\x01\x02\x03\
|
\x04\x16\n\x0c\n\x05\x05\x01\x02\x02\x01\x12\x03\x1a\x04\x11\n\x0c\n\x05\
|
||||||
\x02\x12\x03\x1a\x12\x13b\x06proto3\
|
\x05\x01\x02\x02\x02\x12\x03\x1a\x14\x15\n\x0b\n\x04\x05\x01\x02\x03\x12\
|
||||||
|
\x03\x1b\x04\x14\n\x0c\n\x05\x05\x01\x02\x03\x01\x12\x03\x1b\x04\x0f\n\
|
||||||
|
\x0c\n\x05\x05\x01\x02\x03\x02\x12\x03\x1b\x12\x13b\x06proto3\
|
||||||
";
|
";
|
||||||
|
|
||||||
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;
|
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;
|
||||||
|
@ -21,7 +21,7 @@ message RevisionRange {
|
|||||||
int64 end = 3;
|
int64 end = 3;
|
||||||
}
|
}
|
||||||
enum RevisionState {
|
enum RevisionState {
|
||||||
StateLocal = 0;
|
Local = 0;
|
||||||
Ack = 1;
|
Ack = 1;
|
||||||
}
|
}
|
||||||
enum RevType {
|
enum RevType {
|
||||||
|
@ -19,6 +19,7 @@ message NewDocumentUser {
|
|||||||
}
|
}
|
||||||
enum DocumentClientWSDataType {
|
enum DocumentClientWSDataType {
|
||||||
ClientPushRev = 0;
|
ClientPushRev = 0;
|
||||||
|
ClientPing = 1;
|
||||||
}
|
}
|
||||||
enum DocumentServerWSDataType {
|
enum DocumentServerWSDataType {
|
||||||
ServerAck = 0;
|
ServerAck = 0;
|
||||||
|
@ -40,16 +40,14 @@ impl ServerDocumentManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn apply_revisions(
|
pub async fn handle_client_revisions(
|
||||||
&self,
|
&self,
|
||||||
user: Arc<dyn RevisionUser>,
|
user: Arc<dyn RevisionUser>,
|
||||||
mut client_data: DocumentClientWSData,
|
mut client_data: DocumentClientWSData,
|
||||||
) -> Result<(), CollaborateError> {
|
) -> Result<(), CollaborateError> {
|
||||||
let mut pb = client_data.take_revisions();
|
let mut pb = client_data.take_revisions();
|
||||||
let cloned_user = user.clone();
|
let cloned_user = user.clone();
|
||||||
let ack_id = client_data.id.clone().parse::<i64>().map_err(|e| {
|
let ack_id = rev_id_from_str(&client_data.id)?;
|
||||||
CollaborateError::internal().context(format!("Parse rev_id from {} failed. {}", &client_data.id, e))
|
|
||||||
})?;
|
|
||||||
let doc_id = client_data.doc_id;
|
let doc_id = client_data.doc_id;
|
||||||
|
|
||||||
let revisions = spawn_blocking(move || {
|
let revisions = spawn_blocking(move || {
|
||||||
@ -81,6 +79,23 @@ impl ServerDocumentManager {
|
|||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn handle_client_ping(
|
||||||
|
&self,
|
||||||
|
user: Arc<dyn RevisionUser>,
|
||||||
|
client_data: DocumentClientWSData,
|
||||||
|
) -> Result<(), CollaborateError> {
|
||||||
|
let rev_id = rev_id_from_str(&client_data.id)?;
|
||||||
|
let doc_id = client_data.doc_id.clone();
|
||||||
|
|
||||||
|
match self.get_document_handler(&doc_id).await {
|
||||||
|
None => Ok(()),
|
||||||
|
Some(handler) => {
|
||||||
|
let _ = handler.apply_ping(doc_id.clone(), rev_id, user).await?;
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async fn get_document_handler(&self, doc_id: &str) -> Option<Arc<OpenDocHandle>> {
|
async fn get_document_handler(&self, doc_id: &str) -> Option<Arc<OpenDocHandle>> {
|
||||||
match self.open_doc_map.get(doc_id).map(|ctx| ctx.clone()) {
|
match self.open_doc_map.get(doc_id).map(|ctx| ctx.clone()) {
|
||||||
Some(edit_doc) => Some(edit_doc),
|
Some(edit_doc) => Some(edit_doc),
|
||||||
@ -168,6 +183,27 @@ impl OpenDocHandle {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tracing::instrument(level = "debug", skip(self, user), err)]
|
||||||
|
async fn apply_ping(
|
||||||
|
&self,
|
||||||
|
doc_id: String,
|
||||||
|
rev_id: i64,
|
||||||
|
user: Arc<dyn RevisionUser>,
|
||||||
|
) -> Result<(), CollaborateError> {
|
||||||
|
let (ret, rx) = oneshot::channel();
|
||||||
|
self.users.insert(user.user_id(), user.clone());
|
||||||
|
let persistence = self.persistence.clone();
|
||||||
|
let msg = DocumentCommand::Ping {
|
||||||
|
doc_id,
|
||||||
|
user,
|
||||||
|
persistence,
|
||||||
|
rev_id,
|
||||||
|
ret,
|
||||||
|
};
|
||||||
|
let _ = self.send(msg, rx).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
async fn send<T>(&self, msg: DocumentCommand, rx: oneshot::Receiver<T>) -> CollaborateResult<T> {
|
async fn send<T>(&self, msg: DocumentCommand, rx: oneshot::Receiver<T>) -> CollaborateResult<T> {
|
||||||
let _ = self
|
let _ = self
|
||||||
.sender
|
.sender
|
||||||
@ -193,6 +229,13 @@ enum DocumentCommand {
|
|||||||
persistence: Arc<dyn DocumentPersistence>,
|
persistence: Arc<dyn DocumentPersistence>,
|
||||||
ret: oneshot::Sender<CollaborateResult<()>>,
|
ret: oneshot::Sender<CollaborateResult<()>>,
|
||||||
},
|
},
|
||||||
|
Ping {
|
||||||
|
doc_id: String,
|
||||||
|
user: Arc<dyn RevisionUser>,
|
||||||
|
persistence: Arc<dyn DocumentPersistence>,
|
||||||
|
rev_id: i64,
|
||||||
|
ret: oneshot::Sender<CollaborateResult<()>>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
struct DocumentCommandQueue {
|
struct DocumentCommandQueue {
|
||||||
@ -248,7 +291,20 @@ impl DocumentCommandQueue {
|
|||||||
.sync_revisions(doc_id, user, revisions, persistence)
|
.sync_revisions(doc_id, user, revisions, persistence)
|
||||||
.await
|
.await
|
||||||
.map_err(internal_error);
|
.map_err(internal_error);
|
||||||
log::debug!("handle message {:?}", result);
|
let _ = ret.send(result);
|
||||||
|
},
|
||||||
|
DocumentCommand::Ping {
|
||||||
|
doc_id,
|
||||||
|
user,
|
||||||
|
persistence,
|
||||||
|
rev_id,
|
||||||
|
ret,
|
||||||
|
} => {
|
||||||
|
let result = self
|
||||||
|
.synchronizer
|
||||||
|
.pong(doc_id, user, persistence, rev_id)
|
||||||
|
.await
|
||||||
|
.map_err(internal_error);
|
||||||
let _ = ret.send(result);
|
let _ = ret.send(result);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -260,3 +316,11 @@ impl std::ops::Drop for DocumentCommandQueue {
|
|||||||
log::debug!("{} DocumentCommandQueue drop", self.doc_id);
|
log::debug!("{} DocumentCommandQueue drop", self.doc_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn rev_id_from_str(s: &str) -> Result<i64, CollaborateError> {
|
||||||
|
let rev_id = s
|
||||||
|
.to_owned()
|
||||||
|
.parse::<i64>()
|
||||||
|
.map_err(|e| CollaborateError::internal().context(format!("Parse rev_id from {} failed. {}", s, e)))?;
|
||||||
|
Ok(rev_id)
|
||||||
|
}
|
||||||
|
@ -101,24 +101,33 @@ impl RevisionSynchronizer {
|
|||||||
// delta.
|
// delta.
|
||||||
let from_rev_id = first_revision.rev_id;
|
let from_rev_id = first_revision.rev_id;
|
||||||
let to_rev_id = server_base_rev_id;
|
let to_rev_id = server_base_rev_id;
|
||||||
let rev_ids: Vec<i64> = (from_rev_id..=to_rev_id).collect();
|
let _ = self.push_revisions_to_user(user, persistence, from_rev_id, to_rev_id);
|
||||||
let revisions = match persistence.get_revisions(&self.doc_id, rev_ids).await {
|
|
||||||
Ok(revisions) => {
|
|
||||||
assert_eq!(
|
|
||||||
revisions.is_empty(),
|
|
||||||
false,
|
|
||||||
"revisions should not be empty if the doc exists"
|
|
||||||
);
|
|
||||||
revisions
|
|
||||||
},
|
},
|
||||||
Err(e) => {
|
}
|
||||||
tracing::error!("{}", e);
|
Ok(())
|
||||||
vec![]
|
}
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
let data = DocumentServerWSDataBuilder::build_push_message(&self.doc_id, revisions);
|
pub async fn pong(
|
||||||
user.receive(SyncResponse::Push(data));
|
&self,
|
||||||
|
doc_id: String,
|
||||||
|
user: Arc<dyn RevisionUser>,
|
||||||
|
persistence: Arc<dyn DocumentPersistence>,
|
||||||
|
rev_id: i64,
|
||||||
|
) -> Result<(), CollaborateError> {
|
||||||
|
let server_base_rev_id = self.rev_id.load(SeqCst);
|
||||||
|
match server_base_rev_id.cmp(&rev_id) {
|
||||||
|
Ordering::Less => tracing::error!(
|
||||||
|
"[Pong] Client should not send ping and the server should pull the revisions from the client"
|
||||||
|
),
|
||||||
|
Ordering::Equal => tracing::debug!("[Pong]: The document:{} is up to date.", doc_id),
|
||||||
|
Ordering::Greater => {
|
||||||
|
// The client document is outdated. Transform the client revision delta and then
|
||||||
|
// send the prime delta to the client. Client should compose the this prime
|
||||||
|
// delta.
|
||||||
|
let from_rev_id = rev_id;
|
||||||
|
let to_rev_id = server_base_rev_id;
|
||||||
|
tracing::trace!("[Pong]: Push revisions to user");
|
||||||
|
let _ = self.push_revisions_to_user(user, persistence, from_rev_id, to_rev_id);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -154,20 +163,6 @@ impl RevisionSynchronizer {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// fn mk_revision(&self, base_rev_id: i64, delta: RichTextDelta) -> Revision {
|
|
||||||
// let delta_data = delta.to_bytes().to_vec();
|
|
||||||
// let md5 = md5(&delta_data);
|
|
||||||
// Revision {
|
|
||||||
// base_rev_id,
|
|
||||||
// rev_id: self.rev_id.load(SeqCst),
|
|
||||||
// delta_data,
|
|
||||||
// md5,
|
|
||||||
// doc_id: self.doc_id.to_string(),
|
|
||||||
// ty: RevType::Remote,
|
|
||||||
// user_id: "".to_string(),
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub(crate) fn rev_id(&self) -> i64 { self.rev_id.load(SeqCst) }
|
pub(crate) fn rev_id(&self) -> i64 { self.rev_id.load(SeqCst) }
|
||||||
|
|
||||||
@ -182,6 +177,33 @@ impl RevisionSynchronizer {
|
|||||||
|
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn push_revisions_to_user(
|
||||||
|
&self,
|
||||||
|
user: Arc<dyn RevisionUser>,
|
||||||
|
persistence: Arc<dyn DocumentPersistence>,
|
||||||
|
from: i64,
|
||||||
|
to: i64,
|
||||||
|
) {
|
||||||
|
let rev_ids: Vec<i64> = (from..=to).collect();
|
||||||
|
let revisions = match persistence.get_revisions(&self.doc_id, rev_ids).await {
|
||||||
|
Ok(revisions) => {
|
||||||
|
assert_eq!(
|
||||||
|
revisions.is_empty(),
|
||||||
|
false,
|
||||||
|
"revisions should not be empty if the doc exists"
|
||||||
|
);
|
||||||
|
revisions
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
tracing::error!("{}", e);
|
||||||
|
vec![]
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let data = DocumentServerWSDataBuilder::build_push_message(&self.doc_id, revisions);
|
||||||
|
user.receive(SyncResponse::Push(data));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -97,8 +97,6 @@ impl CreateViewParams {
|
|||||||
view_id,
|
view_id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn take_view_data(&mut self) -> String { std::mem::take(&mut self.view_data) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryInto<CreateViewParams> for CreateViewRequest {
|
impl TryInto<CreateViewParams> for CreateViewRequest {
|
||||||
|
Loading…
Reference in New Issue
Block a user