mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
save revision to disk if not exisgt
This commit is contained in:
parent
1c8d2c5ac0
commit
04f8fc38a8
@ -2,6 +2,7 @@ extend = [
|
|||||||
{ path = "scripts/makefile/desktop.toml" },
|
{ path = "scripts/makefile/desktop.toml" },
|
||||||
{ path = "scripts/makefile/protobuf.toml" },
|
{ path = "scripts/makefile/protobuf.toml" },
|
||||||
{ path = "scripts/makefile/tests.toml" },
|
{ path = "scripts/makefile/tests.toml" },
|
||||||
|
{ path = "scripts/makefile/docker.toml" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[env]
|
[env]
|
||||||
|
@ -9,14 +9,14 @@ import 'package:flowy_sdk/protobuf/flowy-document/doc.pb.dart';
|
|||||||
import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart';
|
||||||
|
|
||||||
class FlowyDoc implements EditorDeltaSender {
|
class FlowyDoc implements EditorDeltaSender {
|
||||||
final Doc doc;
|
final DocDelta doc;
|
||||||
final IDoc iDocImpl;
|
final IDoc iDocImpl;
|
||||||
Document data;
|
Document data;
|
||||||
|
|
||||||
FlowyDoc({required this.doc, required this.data, required this.iDocImpl}) {
|
FlowyDoc({required this.doc, required this.data, required this.iDocImpl}) {
|
||||||
data.sender = this;
|
data.sender = this;
|
||||||
}
|
}
|
||||||
String get id => doc.id;
|
String get id => doc.docId;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void sendNewDelta(Delta changeset, Delta delta) async {
|
void sendNewDelta(Delta changeset, Delta delta) async {
|
||||||
@ -40,7 +40,8 @@ class FlowyDoc implements EditorDeltaSender {
|
|||||||
}
|
}
|
||||||
|
|
||||||
abstract class IDoc {
|
abstract class IDoc {
|
||||||
Future<Either<Doc, WorkspaceError>> readDoc();
|
Future<Either<DocDelta, WorkspaceError>> readDoc();
|
||||||
Future<Either<Doc, WorkspaceError>> applyChangeset({required String json});
|
Future<Either<DocDelta, WorkspaceError>> applyChangeset(
|
||||||
|
{required String json});
|
||||||
Future<Either<Unit, WorkspaceError>> closeDoc();
|
Future<Either<Unit, WorkspaceError>> closeDoc();
|
||||||
}
|
}
|
||||||
|
@ -18,13 +18,14 @@ class IDocImpl extends IDoc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<Either<Doc, WorkspaceError>> readDoc() async {
|
Future<Either<DocDelta, WorkspaceError>> readDoc() async {
|
||||||
final docOrFail = await repo.readDoc();
|
final docOrFail = await repo.readDoc();
|
||||||
return docOrFail;
|
return docOrFail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<Either<Doc, WorkspaceError>> applyChangeset({required String json}) {
|
Future<Either<DocDelta, WorkspaceError>> applyChangeset(
|
||||||
|
{required String json}) {
|
||||||
return repo.applyDelta(data: json);
|
return repo.applyDelta(data: json);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,12 +10,12 @@ class DocRepository {
|
|||||||
required this.docId,
|
required this.docId,
|
||||||
});
|
});
|
||||||
|
|
||||||
Future<Either<Doc, WorkspaceError>> readDoc() {
|
Future<Either<DocDelta, WorkspaceError>> readDoc() {
|
||||||
final request = OpenViewRequest.create()..viewId = docId;
|
final request = OpenViewRequest.create()..viewId = docId;
|
||||||
return WorkspaceEventOpenView(request).send();
|
return WorkspaceEventOpenView(request).send();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Either<Doc, WorkspaceError>> applyDelta({required String data}) {
|
Future<Either<DocDelta, WorkspaceError>> applyDelta({required String data}) {
|
||||||
final request = DocDelta.create()
|
final request = DocDelta.create()
|
||||||
..docId = docId
|
..docId = docId
|
||||||
..data = data;
|
..data = data;
|
||||||
|
@ -241,14 +241,14 @@ class WorkspaceEventOpenView {
|
|||||||
OpenViewRequest request;
|
OpenViewRequest request;
|
||||||
WorkspaceEventOpenView(this.request);
|
WorkspaceEventOpenView(this.request);
|
||||||
|
|
||||||
Future<Either<Doc, WorkspaceError>> send() {
|
Future<Either<DocDelta, WorkspaceError>> send() {
|
||||||
final request = FFIRequest.create()
|
final request = FFIRequest.create()
|
||||||
..event = WorkspaceEvent.OpenView.toString()
|
..event = WorkspaceEvent.OpenView.toString()
|
||||||
..payload = requestToBytes(this.request);
|
..payload = requestToBytes(this.request);
|
||||||
|
|
||||||
return Dispatch.asyncRequest(request)
|
return Dispatch.asyncRequest(request)
|
||||||
.then((bytesResult) => bytesResult.fold(
|
.then((bytesResult) => bytesResult.fold(
|
||||||
(okBytes) => left(Doc.fromBuffer(okBytes)),
|
(okBytes) => left(DocDelta.fromBuffer(okBytes)),
|
||||||
(errBytes) => right(WorkspaceError.fromBuffer(errBytes)),
|
(errBytes) => right(WorkspaceError.fromBuffer(errBytes)),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@ -258,14 +258,14 @@ class WorkspaceEventApplyDocDelta {
|
|||||||
DocDelta request;
|
DocDelta request;
|
||||||
WorkspaceEventApplyDocDelta(this.request);
|
WorkspaceEventApplyDocDelta(this.request);
|
||||||
|
|
||||||
Future<Either<Doc, WorkspaceError>> send() {
|
Future<Either<DocDelta, WorkspaceError>> send() {
|
||||||
final request = FFIRequest.create()
|
final request = FFIRequest.create()
|
||||||
..event = WorkspaceEvent.ApplyDocDelta.toString()
|
..event = WorkspaceEvent.ApplyDocDelta.toString()
|
||||||
..payload = requestToBytes(this.request);
|
..payload = requestToBytes(this.request);
|
||||||
|
|
||||||
return Dispatch.asyncRequest(request)
|
return Dispatch.asyncRequest(request)
|
||||||
.then((bytesResult) => bytesResult.fold(
|
.then((bytesResult) => bytesResult.fold(
|
||||||
(okBytes) => left(Doc.fromBuffer(okBytes)),
|
(okBytes) => left(DocDelta.fromBuffer(okBytes)),
|
||||||
(errBytes) => right(WorkspaceError.fromBuffer(errBytes)),
|
(errBytes) => right(WorkspaceError.fromBuffer(errBytes)),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -76,6 +76,7 @@ class Doc extends $pb.GeneratedMessage {
|
|||||||
..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'id')
|
..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'id')
|
||||||
..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'data')
|
..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'data')
|
||||||
..aInt64(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'revId')
|
..aInt64(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'revId')
|
||||||
|
..aInt64(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'baseRevId')
|
||||||
..hasRequiredFields = false
|
..hasRequiredFields = false
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -84,6 +85,7 @@ class Doc extends $pb.GeneratedMessage {
|
|||||||
$core.String? id,
|
$core.String? id,
|
||||||
$core.String? data,
|
$core.String? data,
|
||||||
$fixnum.Int64? revId,
|
$fixnum.Int64? revId,
|
||||||
|
$fixnum.Int64? baseRevId,
|
||||||
}) {
|
}) {
|
||||||
final _result = create();
|
final _result = create();
|
||||||
if (id != null) {
|
if (id != null) {
|
||||||
@ -95,6 +97,9 @@ class Doc extends $pb.GeneratedMessage {
|
|||||||
if (revId != null) {
|
if (revId != null) {
|
||||||
_result.revId = revId;
|
_result.revId = revId;
|
||||||
}
|
}
|
||||||
|
if (baseRevId != null) {
|
||||||
|
_result.baseRevId = baseRevId;
|
||||||
|
}
|
||||||
return _result;
|
return _result;
|
||||||
}
|
}
|
||||||
factory Doc.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
|
factory Doc.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
|
||||||
@ -144,6 +149,15 @@ class Doc extends $pb.GeneratedMessage {
|
|||||||
$core.bool hasRevId() => $_has(2);
|
$core.bool hasRevId() => $_has(2);
|
||||||
@$pb.TagNumber(3)
|
@$pb.TagNumber(3)
|
||||||
void clearRevId() => clearField(3);
|
void clearRevId() => clearField(3);
|
||||||
|
|
||||||
|
@$pb.TagNumber(4)
|
||||||
|
$fixnum.Int64 get baseRevId => $_getI64(3);
|
||||||
|
@$pb.TagNumber(4)
|
||||||
|
set baseRevId($fixnum.Int64 v) { $_setInt64(3, v); }
|
||||||
|
@$pb.TagNumber(4)
|
||||||
|
$core.bool hasBaseRevId() => $_has(3);
|
||||||
|
@$pb.TagNumber(4)
|
||||||
|
void clearBaseRevId() => clearField(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
class UpdateDocParams extends $pb.GeneratedMessage {
|
class UpdateDocParams extends $pb.GeneratedMessage {
|
||||||
|
@ -26,11 +26,12 @@ const Doc$json = const {
|
|||||||
const {'1': 'id', '3': 1, '4': 1, '5': 9, '10': 'id'},
|
const {'1': 'id', '3': 1, '4': 1, '5': 9, '10': 'id'},
|
||||||
const {'1': 'data', '3': 2, '4': 1, '5': 9, '10': 'data'},
|
const {'1': 'data', '3': 2, '4': 1, '5': 9, '10': 'data'},
|
||||||
const {'1': 'rev_id', '3': 3, '4': 1, '5': 3, '10': 'revId'},
|
const {'1': 'rev_id', '3': 3, '4': 1, '5': 3, '10': 'revId'},
|
||||||
|
const {'1': 'base_rev_id', '3': 4, '4': 1, '5': 3, '10': 'baseRevId'},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Descriptor for `Doc`. Decode as a `google.protobuf.DescriptorProto`.
|
/// Descriptor for `Doc`. Decode as a `google.protobuf.DescriptorProto`.
|
||||||
final $typed_data.Uint8List docDescriptor = $convert.base64Decode('CgNEb2MSDgoCaWQYASABKAlSAmlkEhIKBGRhdGEYAiABKAlSBGRhdGESFQoGcmV2X2lkGAMgASgDUgVyZXZJZA==');
|
final $typed_data.Uint8List docDescriptor = $convert.base64Decode('CgNEb2MSDgoCaWQYASABKAlSAmlkEhIKBGRhdGEYAiABKAlSBGRhdGESFQoGcmV2X2lkGAMgASgDUgVyZXZJZBIeCgtiYXNlX3Jldl9pZBgEIAEoA1IJYmFzZVJldklk');
|
||||||
@$core.Deprecated('Use updateDocParamsDescriptor instead')
|
@$core.Deprecated('Use updateDocParamsDescriptor instead')
|
||||||
const UpdateDocParams$json = const {
|
const UpdateDocParams$json = const {
|
||||||
'1': 'UpdateDocParams',
|
'1': 'UpdateDocParams',
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
include scripts/database/database.mk
|
include scripts/database/database.mk
|
||||||
|
|
||||||
.PHONY: init_database add_migrations run_migrations reset_db echo_db_url
|
.PHONY: init_postgres init_database add_migrations run_migrations reset_db echo_db_url
|
@ -2,9 +2,16 @@
|
|||||||
set -x
|
set -x
|
||||||
set -eo pipefail
|
set -eo pipefail
|
||||||
|
|
||||||
|
#if [[ -z "${RESET}" ]]
|
||||||
|
#then
|
||||||
|
# docker stop flowy
|
||||||
|
# docker rm flowy
|
||||||
|
#fi
|
||||||
|
|
||||||
if [[ -z "${SKIP_DOCKER}" ]]
|
if [[ -z "${SKIP_DOCKER}" ]]
|
||||||
then
|
then
|
||||||
docker run \
|
docker run \
|
||||||
|
--name="flowy" \
|
||||||
-e POSTGRES_USER=${DB_USER} \
|
-e POSTGRES_USER=${DB_USER} \
|
||||||
-e POSTGRES_PASSWORD=${DB_PASSWORD} \
|
-e POSTGRES_PASSWORD=${DB_PASSWORD} \
|
||||||
-e POSTGRES_DB=${DB_NAME} \
|
-e POSTGRES_DB=${DB_NAME} \
|
||||||
|
@ -15,7 +15,7 @@ use flowy_user::services::user::UserSession;
|
|||||||
use crate::helper::{spawn_server, TestServer};
|
use crate::helper::{spawn_server, TestServer};
|
||||||
use flowy_document::protobuf::UpdateDocParams;
|
use flowy_document::protobuf::UpdateDocParams;
|
||||||
|
|
||||||
use flowy_ot::core::{Attribute, Interval};
|
use flowy_ot::core::{Attribute, Delta, Interval};
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
|
|
||||||
pub struct DocumentTest {
|
pub struct DocumentTest {
|
||||||
@ -152,11 +152,14 @@ async fn run_scripts(context: Arc<RwLock<ScriptContext>>, scripts: Vec<DocScript
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn assert_eq(expect: &str, receive: &str) {
|
fn assert_eq(expect: &str, receive: &str) {
|
||||||
if expect != receive {
|
let expected_delta: Delta = serde_json::from_str(expect).unwrap();
|
||||||
log::error!("expect: {}", expect);
|
let target_delta: Delta = serde_json::from_str(receive).unwrap();
|
||||||
log::error!("but receive: {}", receive);
|
|
||||||
|
if expected_delta != target_delta {
|
||||||
|
log::error!("✅ expect: {}", expect,);
|
||||||
|
log::error!("❌ receive: {}", receive);
|
||||||
}
|
}
|
||||||
assert_eq!(expect, receive);
|
assert_eq!(target_delta, expected_delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn create_doc(flowy_test: &FlowyTest) -> String {
|
async fn create_doc(flowy_test: &FlowyTest) -> String {
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
|
use crate::errors::DocResult;
|
||||||
use flowy_derive::ProtoBuf;
|
use flowy_derive::ProtoBuf;
|
||||||
|
use flowy_ot::core::Delta;
|
||||||
|
|
||||||
#[derive(ProtoBuf, Default, Debug, Clone)]
|
#[derive(ProtoBuf, Default, Debug, Clone)]
|
||||||
pub struct CreateDocParams {
|
pub struct CreateDocParams {
|
||||||
@ -28,6 +30,16 @@ pub struct Doc {
|
|||||||
|
|
||||||
#[pb(index = 3)]
|
#[pb(index = 3)]
|
||||||
pub rev_id: i64,
|
pub rev_id: i64,
|
||||||
|
|
||||||
|
#[pb(index = 4)]
|
||||||
|
pub base_rev_id: i64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Doc {
|
||||||
|
pub fn delta(&self) -> DocResult<Delta> {
|
||||||
|
let delta = Delta::from_bytes(&self.data)?;
|
||||||
|
Ok(delta)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(ProtoBuf, Default, Debug, Clone)]
|
#[derive(ProtoBuf, Default, Debug, Clone)]
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use crate::services::util::md5;
|
use crate::services::util::md5;
|
||||||
|
|
||||||
|
use crate::entities::doc::Doc;
|
||||||
use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
|
use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
|
||||||
use flowy_ot::core::Delta;
|
use flowy_ot::core::Delta;
|
||||||
use std::fmt::Formatter;
|
use std::fmt::Formatter;
|
||||||
@ -116,6 +117,18 @@ impl Revision {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn revision_from_doc(doc: Doc, ty: RevType) -> Revision {
|
||||||
|
let delta_data = doc.data.as_bytes();
|
||||||
|
let revision = Revision::new(
|
||||||
|
doc.base_rev_id.clone(),
|
||||||
|
doc.rev_id.clone(),
|
||||||
|
delta_data.to_owned(),
|
||||||
|
&doc.id,
|
||||||
|
ty,
|
||||||
|
);
|
||||||
|
revision
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, ProtoBuf)]
|
#[derive(Debug, Clone, Default, ProtoBuf)]
|
||||||
pub struct RevisionRange {
|
pub struct RevisionRange {
|
||||||
#[pb(index = 1)]
|
#[pb(index = 1)]
|
||||||
|
@ -1,12 +1,5 @@
|
|||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use diesel::SqliteConnection;
|
|
||||||
|
|
||||||
use flowy_database::ConnectionPool;
|
|
||||||
use flowy_net::config::ServerConfig;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
entities::doc::{CreateDocParams, Doc, DocDelta, QueryDocParams},
|
entities::doc::{CreateDocParams, DocDelta, QueryDocParams},
|
||||||
errors::DocError,
|
errors::DocError,
|
||||||
services::{
|
services::{
|
||||||
doc::{doc_controller::DocController, edit::ClientEditDoc},
|
doc::{doc_controller::DocController, edit::ClientEditDoc},
|
||||||
@ -14,6 +7,9 @@ use crate::{
|
|||||||
ws::WsDocumentManager,
|
ws::WsDocumentManager,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
use flowy_database::ConnectionPool;
|
||||||
|
use flowy_net::config::ServerConfig;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
pub trait DocumentUser: Send + Sync {
|
pub trait DocumentUser: Send + Sync {
|
||||||
fn user_dir(&self) -> Result<String, DocError>;
|
fn user_dir(&self) -> Result<String, DocError>;
|
||||||
@ -41,13 +37,13 @@ impl FlowyDocument {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create(&self, params: CreateDocParams, conn: &SqliteConnection) -> Result<(), DocError> {
|
pub fn create(&self, params: CreateDocParams) -> Result<(), DocError> {
|
||||||
let _ = self.doc_ctrl.create(params, conn)?;
|
let _ = self.doc_ctrl.create(params)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn delete(&self, params: QueryDocParams, conn: &SqliteConnection) -> Result<(), DocError> {
|
pub fn delete(&self, params: QueryDocParams) -> Result<(), DocError> {
|
||||||
let _ = self.doc_ctrl.delete(params, conn)?;
|
let _ = self.doc_ctrl.delete(params)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,7 +56,7 @@ impl FlowyDocument {
|
|||||||
Ok(edit_context)
|
Ok(edit_context)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn apply_doc_delta(&self, params: DocDelta) -> Result<Doc, DocError> {
|
pub async fn apply_doc_delta(&self, params: DocDelta) -> Result<DocDelta, DocError> {
|
||||||
// workaround: compare the rust's delta with flutter's delta. Will be removed
|
// workaround: compare the rust's delta with flutter's delta. Will be removed
|
||||||
// very soon
|
// very soon
|
||||||
let doc = self.doc_ctrl.edit_doc(params.clone()).await?;
|
let doc = self.doc_ctrl.edit_doc(params.clone()).await?;
|
||||||
|
@ -230,6 +230,7 @@ pub struct Doc {
|
|||||||
pub id: ::std::string::String,
|
pub id: ::std::string::String,
|
||||||
pub data: ::std::string::String,
|
pub data: ::std::string::String,
|
||||||
pub rev_id: i64,
|
pub rev_id: i64,
|
||||||
|
pub base_rev_id: i64,
|
||||||
// special fields
|
// special fields
|
||||||
pub unknown_fields: ::protobuf::UnknownFields,
|
pub unknown_fields: ::protobuf::UnknownFields,
|
||||||
pub cached_size: ::protobuf::CachedSize,
|
pub cached_size: ::protobuf::CachedSize,
|
||||||
@ -312,6 +313,21 @@ impl Doc {
|
|||||||
pub fn set_rev_id(&mut self, v: i64) {
|
pub fn set_rev_id(&mut self, v: i64) {
|
||||||
self.rev_id = v;
|
self.rev_id = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// int64 base_rev_id = 4;
|
||||||
|
|
||||||
|
|
||||||
|
pub fn get_base_rev_id(&self) -> i64 {
|
||||||
|
self.base_rev_id
|
||||||
|
}
|
||||||
|
pub fn clear_base_rev_id(&mut self) {
|
||||||
|
self.base_rev_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Param is passed by value, moved
|
||||||
|
pub fn set_base_rev_id(&mut self, v: i64) {
|
||||||
|
self.base_rev_id = v;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ::protobuf::Message for Doc {
|
impl ::protobuf::Message for Doc {
|
||||||
@ -336,6 +352,13 @@ impl ::protobuf::Message for Doc {
|
|||||||
let tmp = is.read_int64()?;
|
let tmp = is.read_int64()?;
|
||||||
self.rev_id = tmp;
|
self.rev_id = tmp;
|
||||||
},
|
},
|
||||||
|
4 => {
|
||||||
|
if wire_type != ::protobuf::wire_format::WireTypeVarint {
|
||||||
|
return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
|
||||||
|
}
|
||||||
|
let tmp = is.read_int64()?;
|
||||||
|
self.base_rev_id = tmp;
|
||||||
|
},
|
||||||
_ => {
|
_ => {
|
||||||
::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
|
::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
|
||||||
},
|
},
|
||||||
@ -357,6 +380,9 @@ impl ::protobuf::Message for Doc {
|
|||||||
if self.rev_id != 0 {
|
if self.rev_id != 0 {
|
||||||
my_size += ::protobuf::rt::value_size(3, self.rev_id, ::protobuf::wire_format::WireTypeVarint);
|
my_size += ::protobuf::rt::value_size(3, self.rev_id, ::protobuf::wire_format::WireTypeVarint);
|
||||||
}
|
}
|
||||||
|
if self.base_rev_id != 0 {
|
||||||
|
my_size += ::protobuf::rt::value_size(4, self.base_rev_id, ::protobuf::wire_format::WireTypeVarint);
|
||||||
|
}
|
||||||
my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
|
my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
|
||||||
self.cached_size.set(my_size);
|
self.cached_size.set(my_size);
|
||||||
my_size
|
my_size
|
||||||
@ -372,6 +398,9 @@ impl ::protobuf::Message for Doc {
|
|||||||
if self.rev_id != 0 {
|
if self.rev_id != 0 {
|
||||||
os.write_int64(3, self.rev_id)?;
|
os.write_int64(3, self.rev_id)?;
|
||||||
}
|
}
|
||||||
|
if self.base_rev_id != 0 {
|
||||||
|
os.write_int64(4, self.base_rev_id)?;
|
||||||
|
}
|
||||||
os.write_unknown_fields(self.get_unknown_fields())?;
|
os.write_unknown_fields(self.get_unknown_fields())?;
|
||||||
::std::result::Result::Ok(())
|
::std::result::Result::Ok(())
|
||||||
}
|
}
|
||||||
@ -425,6 +454,11 @@ impl ::protobuf::Message for Doc {
|
|||||||
|m: &Doc| { &m.rev_id },
|
|m: &Doc| { &m.rev_id },
|
||||||
|m: &mut Doc| { &mut m.rev_id },
|
|m: &mut Doc| { &mut m.rev_id },
|
||||||
));
|
));
|
||||||
|
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeInt64>(
|
||||||
|
"base_rev_id",
|
||||||
|
|m: &Doc| { &m.base_rev_id },
|
||||||
|
|m: &mut Doc| { &mut m.base_rev_id },
|
||||||
|
));
|
||||||
::protobuf::reflect::MessageDescriptor::new_pb_name::<Doc>(
|
::protobuf::reflect::MessageDescriptor::new_pb_name::<Doc>(
|
||||||
"Doc",
|
"Doc",
|
||||||
fields,
|
fields,
|
||||||
@ -444,6 +478,7 @@ impl ::protobuf::Clear for Doc {
|
|||||||
self.id.clear();
|
self.id.clear();
|
||||||
self.data.clear();
|
self.data.clear();
|
||||||
self.rev_id = 0;
|
self.rev_id = 0;
|
||||||
|
self.base_rev_id = 0;
|
||||||
self.unknown_fields.clear();
|
self.unknown_fields.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1294,63 +1329,67 @@ impl ::protobuf::reflect::ProtobufValue for QueryDocParams {
|
|||||||
|
|
||||||
static file_descriptor_proto_data: &'static [u8] = b"\
|
static file_descriptor_proto_data: &'static [u8] = b"\
|
||||||
\n\tdoc.proto\"5\n\x0fCreateDocParams\x12\x0e\n\x02id\x18\x01\x20\x01(\t\
|
\n\tdoc.proto\"5\n\x0fCreateDocParams\x12\x0e\n\x02id\x18\x01\x20\x01(\t\
|
||||||
R\x02id\x12\x12\n\x04data\x18\x02\x20\x01(\tR\x04data\"@\n\x03Doc\x12\
|
R\x02id\x12\x12\n\x04data\x18\x02\x20\x01(\tR\x04data\"`\n\x03Doc\x12\
|
||||||
\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12\x12\n\x04data\x18\x02\x20\x01\
|
\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12\x12\n\x04data\x18\x02\x20\x01\
|
||||||
(\tR\x04data\x12\x15\n\x06rev_id\x18\x03\x20\x01(\x03R\x05revId\"S\n\x0f\
|
(\tR\x04data\x12\x15\n\x06rev_id\x18\x03\x20\x01(\x03R\x05revId\x12\x1e\
|
||||||
UpdateDocParams\x12\x15\n\x06doc_id\x18\x01\x20\x01(\tR\x05docId\x12\x12\
|
\n\x0bbase_rev_id\x18\x04\x20\x01(\x03R\tbaseRevId\"S\n\x0fUpdateDocPara\
|
||||||
\n\x04data\x18\x02\x20\x01(\tR\x04data\x12\x15\n\x06rev_id\x18\x03\x20\
|
ms\x12\x15\n\x06doc_id\x18\x01\x20\x01(\tR\x05docId\x12\x12\n\x04data\
|
||||||
\x01(\x03R\x05revId\"5\n\x08DocDelta\x12\x15\n\x06doc_id\x18\x01\x20\x01\
|
\x18\x02\x20\x01(\tR\x04data\x12\x15\n\x06rev_id\x18\x03\x20\x01(\x03R\
|
||||||
(\tR\x05docId\x12\x12\n\x04data\x18\x02\x20\x01(\tR\x04data\"S\n\nNewDoc\
|
\x05revId\"5\n\x08DocDelta\x12\x15\n\x06doc_id\x18\x01\x20\x01(\tR\x05do\
|
||||||
User\x12\x17\n\x07user_id\x18\x01\x20\x01(\tR\x06userId\x12\x15\n\x06rev\
|
cId\x12\x12\n\x04data\x18\x02\x20\x01(\tR\x04data\"S\n\nNewDocUser\x12\
|
||||||
_id\x18\x02\x20\x01(\x03R\x05revId\x12\x15\n\x06doc_id\x18\x03\x20\x01(\
|
\x17\n\x07user_id\x18\x01\x20\x01(\tR\x06userId\x12\x15\n\x06rev_id\x18\
|
||||||
\tR\x05docId\"'\n\x0eQueryDocParams\x12\x15\n\x06doc_id\x18\x01\x20\x01(\
|
\x02\x20\x01(\x03R\x05revId\x12\x15\n\x06doc_id\x18\x03\x20\x01(\tR\x05d\
|
||||||
\tR\x05docIdJ\xa4\x07\n\x06\x12\x04\0\0\x1b\x01\n\x08\n\x01\x0c\x12\x03\
|
ocId\"'\n\x0eQueryDocParams\x12\x15\n\x06doc_id\x18\x01\x20\x01(\tR\x05d\
|
||||||
\0\0\x12\n\n\n\x02\x04\0\x12\x04\x02\0\x05\x01\n\n\n\x03\x04\0\x01\x12\
|
ocIdJ\xdb\x07\n\x06\x12\x04\0\0\x1c\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\
|
||||||
\x03\x02\x08\x17\n\x0b\n\x04\x04\0\x02\0\x12\x03\x03\x04\x12\n\x0c\n\x05\
|
\n\n\n\x02\x04\0\x12\x04\x02\0\x05\x01\n\n\n\x03\x04\0\x01\x12\x03\x02\
|
||||||
\x04\0\x02\0\x05\x12\x03\x03\x04\n\n\x0c\n\x05\x04\0\x02\0\x01\x12\x03\
|
\x08\x17\n\x0b\n\x04\x04\0\x02\0\x12\x03\x03\x04\x12\n\x0c\n\x05\x04\0\
|
||||||
\x03\x0b\r\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x03\x10\x11\n\x0b\n\x04\
|
\x02\0\x05\x12\x03\x03\x04\n\n\x0c\n\x05\x04\0\x02\0\x01\x12\x03\x03\x0b\
|
||||||
\x04\0\x02\x01\x12\x03\x04\x04\x14\n\x0c\n\x05\x04\0\x02\x01\x05\x12\x03\
|
\r\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x03\x10\x11\n\x0b\n\x04\x04\0\x02\
|
||||||
\x04\x04\n\n\x0c\n\x05\x04\0\x02\x01\x01\x12\x03\x04\x0b\x0f\n\x0c\n\x05\
|
\x01\x12\x03\x04\x04\x14\n\x0c\n\x05\x04\0\x02\x01\x05\x12\x03\x04\x04\n\
|
||||||
\x04\0\x02\x01\x03\x12\x03\x04\x12\x13\n\n\n\x02\x04\x01\x12\x04\x06\0\n\
|
\n\x0c\n\x05\x04\0\x02\x01\x01\x12\x03\x04\x0b\x0f\n\x0c\n\x05\x04\0\x02\
|
||||||
\x01\n\n\n\x03\x04\x01\x01\x12\x03\x06\x08\x0b\n\x0b\n\x04\x04\x01\x02\0\
|
\x01\x03\x12\x03\x04\x12\x13\n\n\n\x02\x04\x01\x12\x04\x06\0\x0b\x01\n\n\
|
||||||
\x12\x03\x07\x04\x12\n\x0c\n\x05\x04\x01\x02\0\x05\x12\x03\x07\x04\n\n\
|
\n\x03\x04\x01\x01\x12\x03\x06\x08\x0b\n\x0b\n\x04\x04\x01\x02\0\x12\x03\
|
||||||
\x0c\n\x05\x04\x01\x02\0\x01\x12\x03\x07\x0b\r\n\x0c\n\x05\x04\x01\x02\0\
|
\x07\x04\x12\n\x0c\n\x05\x04\x01\x02\0\x05\x12\x03\x07\x04\n\n\x0c\n\x05\
|
||||||
\x03\x12\x03\x07\x10\x11\n\x0b\n\x04\x04\x01\x02\x01\x12\x03\x08\x04\x14\
|
\x04\x01\x02\0\x01\x12\x03\x07\x0b\r\n\x0c\n\x05\x04\x01\x02\0\x03\x12\
|
||||||
\n\x0c\n\x05\x04\x01\x02\x01\x05\x12\x03\x08\x04\n\n\x0c\n\x05\x04\x01\
|
\x03\x07\x10\x11\n\x0b\n\x04\x04\x01\x02\x01\x12\x03\x08\x04\x14\n\x0c\n\
|
||||||
\x02\x01\x01\x12\x03\x08\x0b\x0f\n\x0c\n\x05\x04\x01\x02\x01\x03\x12\x03\
|
\x05\x04\x01\x02\x01\x05\x12\x03\x08\x04\n\n\x0c\n\x05\x04\x01\x02\x01\
|
||||||
\x08\x12\x13\n\x0b\n\x04\x04\x01\x02\x02\x12\x03\t\x04\x15\n\x0c\n\x05\
|
\x01\x12\x03\x08\x0b\x0f\n\x0c\n\x05\x04\x01\x02\x01\x03\x12\x03\x08\x12\
|
||||||
\x04\x01\x02\x02\x05\x12\x03\t\x04\t\n\x0c\n\x05\x04\x01\x02\x02\x01\x12\
|
\x13\n\x0b\n\x04\x04\x01\x02\x02\x12\x03\t\x04\x15\n\x0c\n\x05\x04\x01\
|
||||||
\x03\t\n\x10\n\x0c\n\x05\x04\x01\x02\x02\x03\x12\x03\t\x13\x14\n\n\n\x02\
|
\x02\x02\x05\x12\x03\t\x04\t\n\x0c\n\x05\x04\x01\x02\x02\x01\x12\x03\t\n\
|
||||||
\x04\x02\x12\x04\x0b\0\x0f\x01\n\n\n\x03\x04\x02\x01\x12\x03\x0b\x08\x17\
|
\x10\n\x0c\n\x05\x04\x01\x02\x02\x03\x12\x03\t\x13\x14\n\x0b\n\x04\x04\
|
||||||
\n\x0b\n\x04\x04\x02\x02\0\x12\x03\x0c\x04\x16\n\x0c\n\x05\x04\x02\x02\0\
|
\x01\x02\x03\x12\x03\n\x04\x1a\n\x0c\n\x05\x04\x01\x02\x03\x05\x12\x03\n\
|
||||||
\x05\x12\x03\x0c\x04\n\n\x0c\n\x05\x04\x02\x02\0\x01\x12\x03\x0c\x0b\x11\
|
\x04\t\n\x0c\n\x05\x04\x01\x02\x03\x01\x12\x03\n\n\x15\n\x0c\n\x05\x04\
|
||||||
\n\x0c\n\x05\x04\x02\x02\0\x03\x12\x03\x0c\x14\x15\n\x0b\n\x04\x04\x02\
|
\x01\x02\x03\x03\x12\x03\n\x18\x19\n\n\n\x02\x04\x02\x12\x04\x0c\0\x10\
|
||||||
\x02\x01\x12\x03\r\x04\x14\n\x0c\n\x05\x04\x02\x02\x01\x05\x12\x03\r\x04\
|
\x01\n\n\n\x03\x04\x02\x01\x12\x03\x0c\x08\x17\n\x0b\n\x04\x04\x02\x02\0\
|
||||||
\n\n\x0c\n\x05\x04\x02\x02\x01\x01\x12\x03\r\x0b\x0f\n\x0c\n\x05\x04\x02\
|
\x12\x03\r\x04\x16\n\x0c\n\x05\x04\x02\x02\0\x05\x12\x03\r\x04\n\n\x0c\n\
|
||||||
\x02\x01\x03\x12\x03\r\x12\x13\n\x0b\n\x04\x04\x02\x02\x02\x12\x03\x0e\
|
\x05\x04\x02\x02\0\x01\x12\x03\r\x0b\x11\n\x0c\n\x05\x04\x02\x02\0\x03\
|
||||||
\x04\x15\n\x0c\n\x05\x04\x02\x02\x02\x05\x12\x03\x0e\x04\t\n\x0c\n\x05\
|
\x12\x03\r\x14\x15\n\x0b\n\x04\x04\x02\x02\x01\x12\x03\x0e\x04\x14\n\x0c\
|
||||||
\x04\x02\x02\x02\x01\x12\x03\x0e\n\x10\n\x0c\n\x05\x04\x02\x02\x02\x03\
|
\n\x05\x04\x02\x02\x01\x05\x12\x03\x0e\x04\n\n\x0c\n\x05\x04\x02\x02\x01\
|
||||||
\x12\x03\x0e\x13\x14\n\n\n\x02\x04\x03\x12\x04\x10\0\x13\x01\n\n\n\x03\
|
\x01\x12\x03\x0e\x0b\x0f\n\x0c\n\x05\x04\x02\x02\x01\x03\x12\x03\x0e\x12\
|
||||||
\x04\x03\x01\x12\x03\x10\x08\x10\n\x0b\n\x04\x04\x03\x02\0\x12\x03\x11\
|
\x13\n\x0b\n\x04\x04\x02\x02\x02\x12\x03\x0f\x04\x15\n\x0c\n\x05\x04\x02\
|
||||||
\x04\x16\n\x0c\n\x05\x04\x03\x02\0\x05\x12\x03\x11\x04\n\n\x0c\n\x05\x04\
|
\x02\x02\x05\x12\x03\x0f\x04\t\n\x0c\n\x05\x04\x02\x02\x02\x01\x12\x03\
|
||||||
\x03\x02\0\x01\x12\x03\x11\x0b\x11\n\x0c\n\x05\x04\x03\x02\0\x03\x12\x03\
|
\x0f\n\x10\n\x0c\n\x05\x04\x02\x02\x02\x03\x12\x03\x0f\x13\x14\n\n\n\x02\
|
||||||
\x11\x14\x15\n\x0b\n\x04\x04\x03\x02\x01\x12\x03\x12\x04\x14\n\x0c\n\x05\
|
\x04\x03\x12\x04\x11\0\x14\x01\n\n\n\x03\x04\x03\x01\x12\x03\x11\x08\x10\
|
||||||
\x04\x03\x02\x01\x05\x12\x03\x12\x04\n\n\x0c\n\x05\x04\x03\x02\x01\x01\
|
\n\x0b\n\x04\x04\x03\x02\0\x12\x03\x12\x04\x16\n\x0c\n\x05\x04\x03\x02\0\
|
||||||
\x12\x03\x12\x0b\x0f\n\x0c\n\x05\x04\x03\x02\x01\x03\x12\x03\x12\x12\x13\
|
\x05\x12\x03\x12\x04\n\n\x0c\n\x05\x04\x03\x02\0\x01\x12\x03\x12\x0b\x11\
|
||||||
\n\n\n\x02\x04\x04\x12\x04\x14\0\x18\x01\n\n\n\x03\x04\x04\x01\x12\x03\
|
\n\x0c\n\x05\x04\x03\x02\0\x03\x12\x03\x12\x14\x15\n\x0b\n\x04\x04\x03\
|
||||||
\x14\x08\x12\n\x0b\n\x04\x04\x04\x02\0\x12\x03\x15\x04\x17\n\x0c\n\x05\
|
\x02\x01\x12\x03\x13\x04\x14\n\x0c\n\x05\x04\x03\x02\x01\x05\x12\x03\x13\
|
||||||
\x04\x04\x02\0\x05\x12\x03\x15\x04\n\n\x0c\n\x05\x04\x04\x02\0\x01\x12\
|
\x04\n\n\x0c\n\x05\x04\x03\x02\x01\x01\x12\x03\x13\x0b\x0f\n\x0c\n\x05\
|
||||||
\x03\x15\x0b\x12\n\x0c\n\x05\x04\x04\x02\0\x03\x12\x03\x15\x15\x16\n\x0b\
|
\x04\x03\x02\x01\x03\x12\x03\x13\x12\x13\n\n\n\x02\x04\x04\x12\x04\x15\0\
|
||||||
\n\x04\x04\x04\x02\x01\x12\x03\x16\x04\x15\n\x0c\n\x05\x04\x04\x02\x01\
|
\x19\x01\n\n\n\x03\x04\x04\x01\x12\x03\x15\x08\x12\n\x0b\n\x04\x04\x04\
|
||||||
\x05\x12\x03\x16\x04\t\n\x0c\n\x05\x04\x04\x02\x01\x01\x12\x03\x16\n\x10\
|
\x02\0\x12\x03\x16\x04\x17\n\x0c\n\x05\x04\x04\x02\0\x05\x12\x03\x16\x04\
|
||||||
\n\x0c\n\x05\x04\x04\x02\x01\x03\x12\x03\x16\x13\x14\n\x0b\n\x04\x04\x04\
|
\n\n\x0c\n\x05\x04\x04\x02\0\x01\x12\x03\x16\x0b\x12\n\x0c\n\x05\x04\x04\
|
||||||
\x02\x02\x12\x03\x17\x04\x16\n\x0c\n\x05\x04\x04\x02\x02\x05\x12\x03\x17\
|
\x02\0\x03\x12\x03\x16\x15\x16\n\x0b\n\x04\x04\x04\x02\x01\x12\x03\x17\
|
||||||
\x04\n\n\x0c\n\x05\x04\x04\x02\x02\x01\x12\x03\x17\x0b\x11\n\x0c\n\x05\
|
\x04\x15\n\x0c\n\x05\x04\x04\x02\x01\x05\x12\x03\x17\x04\t\n\x0c\n\x05\
|
||||||
\x04\x04\x02\x02\x03\x12\x03\x17\x14\x15\n\n\n\x02\x04\x05\x12\x04\x19\0\
|
\x04\x04\x02\x01\x01\x12\x03\x17\n\x10\n\x0c\n\x05\x04\x04\x02\x01\x03\
|
||||||
\x1b\x01\n\n\n\x03\x04\x05\x01\x12\x03\x19\x08\x16\n\x0b\n\x04\x04\x05\
|
\x12\x03\x17\x13\x14\n\x0b\n\x04\x04\x04\x02\x02\x12\x03\x18\x04\x16\n\
|
||||||
\x02\0\x12\x03\x1a\x04\x16\n\x0c\n\x05\x04\x05\x02\0\x05\x12\x03\x1a\x04\
|
\x0c\n\x05\x04\x04\x02\x02\x05\x12\x03\x18\x04\n\n\x0c\n\x05\x04\x04\x02\
|
||||||
\n\n\x0c\n\x05\x04\x05\x02\0\x01\x12\x03\x1a\x0b\x11\n\x0c\n\x05\x04\x05\
|
\x02\x01\x12\x03\x18\x0b\x11\n\x0c\n\x05\x04\x04\x02\x02\x03\x12\x03\x18\
|
||||||
\x02\0\x03\x12\x03\x1a\x14\x15b\x06proto3\
|
\x14\x15\n\n\n\x02\x04\x05\x12\x04\x1a\0\x1c\x01\n\n\n\x03\x04\x05\x01\
|
||||||
|
\x12\x03\x1a\x08\x16\n\x0b\n\x04\x04\x05\x02\0\x12\x03\x1b\x04\x16\n\x0c\
|
||||||
|
\n\x05\x04\x05\x02\0\x05\x12\x03\x1b\x04\n\n\x0c\n\x05\x04\x05\x02\0\x01\
|
||||||
|
\x12\x03\x1b\x0b\x11\n\x0c\n\x05\x04\x05\x02\0\x03\x12\x03\x1b\x14\x15b\
|
||||||
|
\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;
|
||||||
|
@ -8,6 +8,7 @@ message Doc {
|
|||||||
string id = 1;
|
string id = 1;
|
||||||
string data = 2;
|
string data = 2;
|
||||||
int64 rev_id = 3;
|
int64 rev_id = 3;
|
||||||
|
int64 base_rev_id = 4;
|
||||||
}
|
}
|
||||||
message UpdateDocParams {
|
message UpdateDocParams {
|
||||||
string doc_id = 1;
|
string doc_id = 1;
|
||||||
|
@ -4,7 +4,7 @@ use bytes::Bytes;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
entities::doc::{CreateDocParams, Doc, DocDelta, QueryDocParams},
|
entities::doc::{CreateDocParams, Doc, DocDelta, QueryDocParams},
|
||||||
errors::{internal_error, DocError, DocResult},
|
errors::{DocError, DocResult},
|
||||||
module::DocumentUser,
|
module::DocumentUser,
|
||||||
services::{
|
services::{
|
||||||
cache::DocCache,
|
cache::DocCache,
|
||||||
@ -16,7 +16,7 @@ use crate::{
|
|||||||
ws::WsDocumentManager,
|
ws::WsDocumentManager,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use flowy_database::{ConnectionPool, SqliteConnection};
|
use flowy_database::ConnectionPool;
|
||||||
use flowy_infra::future::{wrap_future, FnFuture, ResultFuture};
|
use flowy_infra::future::{wrap_future, FnFuture, ResultFuture};
|
||||||
use flowy_ot::core::Delta;
|
use flowy_ot::core::Delta;
|
||||||
use tokio::time::{interval, Duration};
|
use tokio::time::{interval, Duration};
|
||||||
@ -45,8 +45,8 @@ impl DocController {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(skip(self, conn), err)]
|
#[tracing::instrument(skip(self), err)]
|
||||||
pub(crate) fn create(&self, params: CreateDocParams, conn: &SqliteConnection) -> Result<(), DocError> {
|
pub(crate) fn create(&self, params: CreateDocParams) -> Result<(), DocError> {
|
||||||
// let _doc = Doc {
|
// let _doc = Doc {
|
||||||
// id: params.id,
|
// id: params.id,
|
||||||
// data: params.data,
|
// data: params.data,
|
||||||
@ -77,8 +77,8 @@ impl DocController {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(level = "debug", skip(self, conn), err)]
|
#[tracing::instrument(level = "debug", skip(self), err)]
|
||||||
pub(crate) fn delete(&self, params: QueryDocParams, conn: &SqliteConnection) -> Result<(), DocError> {
|
pub(crate) fn delete(&self, params: QueryDocParams) -> Result<(), DocError> {
|
||||||
let doc_id = ¶ms.doc_id;
|
let doc_id = ¶ms.doc_id;
|
||||||
self.cache.remove(doc_id);
|
self.cache.remove(doc_id);
|
||||||
self.ws_manager.remove_handler(doc_id);
|
self.ws_manager.remove_handler(doc_id);
|
||||||
@ -87,10 +87,10 @@ impl DocController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(level = "debug", skip(self, delta), err)]
|
#[tracing::instrument(level = "debug", skip(self, delta), err)]
|
||||||
pub(crate) async fn edit_doc(&self, delta: DocDelta) -> Result<Doc, DocError> {
|
pub(crate) async fn edit_doc(&self, delta: DocDelta) -> Result<DocDelta, DocError> {
|
||||||
let edit_doc_ctx = self.cache.get(&delta.doc_id)?;
|
let edit_doc_ctx = self.cache.get(&delta.doc_id)?;
|
||||||
let _ = edit_doc_ctx.compose_local_delta(Bytes::from(delta.data)).await?;
|
let _ = edit_doc_ctx.compose_local_delta(Bytes::from(delta.data)).await?;
|
||||||
Ok(edit_doc_ctx.doc().await?)
|
Ok(edit_doc_ctx.delta().await?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,7 +137,7 @@ struct RevisionServerImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl RevisionServer for RevisionServerImpl {
|
impl RevisionServer for RevisionServerImpl {
|
||||||
fn fetch_document_from_remote(&self, doc_id: &str) -> ResultFuture<DocRevision, DocError> {
|
fn fetch_document_from_remote(&self, doc_id: &str) -> ResultFuture<Doc, DocError> {
|
||||||
let params = QueryDocParams {
|
let params = QueryDocParams {
|
||||||
doc_id: doc_id.to_string(),
|
doc_id: doc_id.to_string(),
|
||||||
};
|
};
|
||||||
@ -147,14 +147,7 @@ impl RevisionServer for RevisionServerImpl {
|
|||||||
ResultFuture::new(async move {
|
ResultFuture::new(async move {
|
||||||
match server.read_doc(&token, params).await? {
|
match server.read_doc(&token, params).await? {
|
||||||
None => Err(DocError::not_found()),
|
None => Err(DocError::not_found()),
|
||||||
Some(doc) => {
|
Some(doc) => Ok(doc),
|
||||||
let delta = Delta::from_bytes(doc.data)?;
|
|
||||||
Ok(DocRevision {
|
|
||||||
base_rev_id: 0.into(),
|
|
||||||
rev_id: doc.rev_id.into(),
|
|
||||||
delta,
|
|
||||||
})
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
entities::doc::{RevId, Revision},
|
entities::doc::{RevId, Revision},
|
||||||
errors::{internal_error, DocResult},
|
errors::DocResult,
|
||||||
services::doc::{
|
services::doc::{
|
||||||
edit::{
|
edit::{
|
||||||
message::{DocumentMsg, TransformDeltas},
|
message::{DocumentMsg, TransformDeltas},
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
entities::{
|
entities::{
|
||||||
doc::{Doc, RevId, RevType, Revision, RevisionRange},
|
doc::{Doc, DocDelta, RevId, RevType, Revision, RevisionRange},
|
||||||
ws::{WsDataType, WsDocumentData},
|
ws::{WsDataType, WsDocumentData},
|
||||||
},
|
},
|
||||||
errors::{internal_error, DocError, DocResult},
|
errors::{internal_error, DocError, DocResult},
|
||||||
@ -46,12 +46,9 @@ impl ClientEditDoc {
|
|||||||
user: Arc<dyn DocumentUser>,
|
user: Arc<dyn DocumentUser>,
|
||||||
) -> DocResult<Self> {
|
) -> DocResult<Self> {
|
||||||
let rev_store = spawn_rev_store_actor(doc_id, pool.clone(), server.clone());
|
let rev_store = spawn_rev_store_actor(doc_id, pool.clone(), server.clone());
|
||||||
let DocRevision {
|
let doc = load_document(rev_store.clone()).await?;
|
||||||
base_rev_id: _,
|
let delta = doc.delta()?;
|
||||||
rev_id,
|
let rev_manager = Arc::new(RevisionManager::new(doc_id, doc.rev_id.into(), rev_store));
|
||||||
delta,
|
|
||||||
} = load_document(rev_store.clone()).await?;
|
|
||||||
let rev_manager = Arc::new(RevisionManager::new(doc_id, rev_id, rev_store));
|
|
||||||
let document = spawn_doc_edit_actor(doc_id, delta, pool.clone());
|
let document = spawn_doc_edit_actor(doc_id, delta, pool.clone());
|
||||||
let doc_id = doc_id.to_string();
|
let doc_id = doc_id.to_string();
|
||||||
let edit_doc = Self {
|
let edit_doc = Self {
|
||||||
@ -142,15 +139,16 @@ impl ClientEditDoc {
|
|||||||
rx.await.map_err(internal_error)?
|
rx.await.map_err(internal_error)?
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn doc(&self) -> DocResult<Doc> {
|
pub async fn delta(&self) -> DocResult<DocDelta> {
|
||||||
let (ret, rx) = oneshot::channel::<DocResult<String>>();
|
let (ret, rx) = oneshot::channel::<DocResult<String>>();
|
||||||
let msg = DocumentMsg::Doc { ret };
|
let msg = DocumentMsg::Doc { ret };
|
||||||
let _ = self.document.send(msg);
|
let _ = self.document.send(msg);
|
||||||
let data = rx.await.map_err(internal_error)??;
|
let data = rx.await.map_err(internal_error)??;
|
||||||
let rev_id = self.rev_manager.rev_id();
|
|
||||||
let id = self.doc_id.clone();
|
|
||||||
|
|
||||||
Ok(Doc { id, data, rev_id })
|
Ok(DocDelta {
|
||||||
|
doc_id: self.doc_id.clone(),
|
||||||
|
data,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn mk_revision(&self, delta_data: &Bytes) -> Result<RevId, DocError> {
|
async fn mk_revision(&self, delta_data: &Bytes) -> Result<RevId, DocError> {
|
||||||
@ -229,7 +227,7 @@ impl ClientEditDoc {
|
|||||||
let _ = rx.await.map_err(internal_error)??;
|
let _ = rx.await.map_err(internal_error)??;
|
||||||
|
|
||||||
// update rev id
|
// update rev id
|
||||||
self.rev_manager.update_rev_id(server_rev_id.clone().into());
|
self.rev_manager.set_rev_id(server_rev_id.clone().into());
|
||||||
let (_, local_rev_id) = self.rev_manager.next_rev_id();
|
let (_, local_rev_id) = self.rev_manager.next_rev_id();
|
||||||
|
|
||||||
// save the revision
|
// save the revision
|
||||||
@ -327,7 +325,7 @@ fn spawn_doc_edit_actor(doc_id: &str, delta: Delta, pool: Arc<ConnectionPool>) -
|
|||||||
sender
|
sender
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn load_document(sender: mpsc::Sender<RevisionCmd>) -> DocResult<DocRevision> {
|
async fn load_document(sender: mpsc::Sender<RevisionCmd>) -> DocResult<Doc> {
|
||||||
let (ret, rx) = oneshot::channel();
|
let (ret, rx) = oneshot::channel();
|
||||||
let _ = sender.send(RevisionCmd::DocumentDelta { ret }).await;
|
let _ = sender.send(RevisionCmd::DocumentDelta { ret }).await;
|
||||||
let result = rx.await.map_err(internal_error)?;
|
let result = rx.await.map_err(internal_error)?;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
entities::doc::{RevId, RevType, Revision, RevisionRange},
|
entities::doc::{Doc, RevId, RevType, Revision, RevisionRange},
|
||||||
errors::{internal_error, DocError},
|
errors::{internal_error, DocError},
|
||||||
services::{doc::revision::store_actor::RevisionCmd, util::RevIdCounter, ws::DocumentWebSocket},
|
services::{doc::revision::store_actor::RevisionCmd, util::RevIdCounter, ws::DocumentWebSocket},
|
||||||
};
|
};
|
||||||
@ -14,7 +14,7 @@ pub struct DocRevision {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub trait RevisionServer: Send + Sync {
|
pub trait RevisionServer: Send + Sync {
|
||||||
fn fetch_document_from_remote(&self, doc_id: &str) -> ResultFuture<DocRevision, DocError>;
|
fn fetch_document_from_remote(&self, doc_id: &str) -> ResultFuture<Doc, DocError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct RevisionManager {
|
pub struct RevisionManager {
|
||||||
@ -60,7 +60,7 @@ impl RevisionManager {
|
|||||||
(cur, next)
|
(cur, next)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_rev_id(&self, rev_id: i64) { self.rev_id_counter.set(rev_id); }
|
pub fn set_rev_id(&self, rev_id: i64) { self.rev_id_counter.set(rev_id); }
|
||||||
|
|
||||||
pub async fn construct_revisions(&self, range: RevisionRange) -> Result<Revision, DocError> {
|
pub async fn construct_revisions(&self, range: RevisionRange) -> Result<Revision, DocError> {
|
||||||
debug_assert!(&range.doc_id == &self.doc_id);
|
debug_assert!(&range.doc_id == &self.doc_id);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
entities::doc::{RevId, RevType, Revision, RevisionRange},
|
entities::doc::{revision_from_doc, Doc, RevId, RevType, Revision, RevisionRange},
|
||||||
errors::{internal_error, DocError, DocResult},
|
errors::{internal_error, DocError, DocResult},
|
||||||
services::doc::revision::{model::RevisionOperation, DocRevision, RevisionServer},
|
services::doc::revision::{model::RevisionOperation, DocRevision, RevisionServer},
|
||||||
sql_tables::{RevState, RevTableSql},
|
sql_tables::{RevState, RevTableSql},
|
||||||
@ -28,7 +28,7 @@ pub enum RevisionCmd {
|
|||||||
ret: oneshot::Sender<DocResult<Vec<Revision>>>,
|
ret: oneshot::Sender<DocResult<Vec<Revision>>>,
|
||||||
},
|
},
|
||||||
DocumentDelta {
|
DocumentDelta {
|
||||||
ret: oneshot::Sender<DocResult<DocRevision>>,
|
ret: oneshot::Sender<DocResult<Doc>>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,35 +181,22 @@ impl RevisionStoreActor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn fetch_document(&self) -> DocResult<DocRevision> {
|
async fn fetch_document(&self) -> DocResult<Doc> {
|
||||||
let result = fetch_from_local(&self.doc_id, self.persistence.clone()).await;
|
let result = fetch_from_local(&self.doc_id, self.persistence.clone()).await;
|
||||||
if result.is_ok() {
|
if result.is_ok() {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
match self.server.fetch_document_from_remote(&self.doc_id).await {
|
let doc = self.server.fetch_document_from_remote(&self.doc_id).await?;
|
||||||
Ok(doc_revision) => {
|
let revision = revision_from_doc(doc.clone(), RevType::Remote);
|
||||||
let delta_data = doc_revision.delta.to_bytes();
|
|
||||||
let revision = Revision::new(
|
|
||||||
doc_revision.base_rev_id.clone(),
|
|
||||||
doc_revision.rev_id.clone(),
|
|
||||||
delta_data.to_vec(),
|
|
||||||
&self.doc_id,
|
|
||||||
RevType::Remote,
|
|
||||||
);
|
|
||||||
self.handle_new_revision(revision);
|
self.handle_new_revision(revision);
|
||||||
|
Ok(doc)
|
||||||
Ok(doc_revision)
|
|
||||||
},
|
|
||||||
Err(e) => Err(e),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn fetch_from_local(doc_id: &str, persistence: Arc<Persistence>) -> DocResult<DocRevision> {
|
async fn fetch_from_local(doc_id: &str, persistence: Arc<Persistence>) -> DocResult<Doc> {
|
||||||
let doc_id = doc_id.to_owned();
|
let doc_id = doc_id.to_owned();
|
||||||
spawn_blocking(move || {
|
spawn_blocking(move || {
|
||||||
// tokio::time::timeout
|
|
||||||
let conn = &*persistence.pool.get().map_err(internal_error)?;
|
let conn = &*persistence.pool.get().map_err(internal_error)?;
|
||||||
let revisions = persistence.rev_sql.read_rev_tables(&doc_id, None, conn)?;
|
let revisions = persistence.rev_sql.read_rev_tables(&doc_id, None, conn)?;
|
||||||
if revisions.is_empty() {
|
if revisions.is_empty() {
|
||||||
@ -230,12 +217,11 @@ async fn fetch_from_local(doc_id: &str, persistence: Arc<Persistence>) -> DocRes
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delta.insert("\n", Attributes::default());
|
Result::<Doc, DocError>::Ok(Doc {
|
||||||
|
id: doc_id,
|
||||||
Result::<DocRevision, DocError>::Ok(DocRevision {
|
data: delta.to_json(),
|
||||||
base_rev_id,
|
rev_id: rev_id.into(),
|
||||||
rev_id,
|
base_rev_id: base_rev_id.into(),
|
||||||
delta,
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
|
@ -46,10 +46,10 @@ pub enum WorkspaceEvent {
|
|||||||
#[event(input = "DeleteViewRequest")]
|
#[event(input = "DeleteViewRequest")]
|
||||||
DeleteView = 204,
|
DeleteView = 204,
|
||||||
|
|
||||||
#[event(input = "OpenViewRequest", output = "Doc")]
|
#[event(input = "OpenViewRequest", output = "DocDelta")]
|
||||||
OpenView = 205,
|
OpenView = 205,
|
||||||
|
|
||||||
#[event(input = "DocDelta", output = "Doc")]
|
#[event(input = "DocDelta", output = "DocDelta")]
|
||||||
ApplyDocDelta = 206,
|
ApplyDocDelta = 206,
|
||||||
|
|
||||||
#[event()]
|
#[event()]
|
||||||
|
@ -15,7 +15,7 @@ use crate::{
|
|||||||
services::ViewController,
|
services::ViewController,
|
||||||
};
|
};
|
||||||
use flowy_dispatch::prelude::{data_result, Data, DataResult, Unit};
|
use flowy_dispatch::prelude::{data_result, Data, DataResult, Unit};
|
||||||
use flowy_document::entities::doc::{Doc, DocDelta, QueryDocParams};
|
use flowy_document::entities::doc::{DocDelta, QueryDocParams};
|
||||||
use std::{convert::TryInto, sync::Arc};
|
use std::{convert::TryInto, sync::Arc};
|
||||||
|
|
||||||
#[tracing::instrument(skip(data, controller), err)]
|
#[tracing::instrument(skip(data, controller), err)]
|
||||||
@ -58,7 +58,7 @@ pub(crate) async fn update_view_handler(
|
|||||||
pub(crate) async fn apply_doc_delta_handler(
|
pub(crate) async fn apply_doc_delta_handler(
|
||||||
data: Data<DocDelta>,
|
data: Data<DocDelta>,
|
||||||
controller: Unit<Arc<ViewController>>,
|
controller: Unit<Arc<ViewController>>,
|
||||||
) -> DataResult<Doc, WorkspaceError> {
|
) -> DataResult<DocDelta, WorkspaceError> {
|
||||||
// let params: DocDelta = data.into_inner().try_into()?;
|
// let params: DocDelta = data.into_inner().try_into()?;
|
||||||
let doc = controller.apply_doc_delta(data.into_inner()).await?;
|
let doc = controller.apply_doc_delta(data.into_inner()).await?;
|
||||||
data_result(doc)
|
data_result(doc)
|
||||||
@ -78,7 +78,7 @@ pub(crate) async fn delete_view_handler(
|
|||||||
pub(crate) async fn open_view_handler(
|
pub(crate) async fn open_view_handler(
|
||||||
data: Data<OpenViewRequest>,
|
data: Data<OpenViewRequest>,
|
||||||
controller: Unit<Arc<ViewController>>,
|
controller: Unit<Arc<ViewController>>,
|
||||||
) -> DataResult<Doc, WorkspaceError> {
|
) -> DataResult<DocDelta, WorkspaceError> {
|
||||||
let params: QueryDocParams = data.into_inner().try_into()?;
|
let params: QueryDocParams = data.into_inner().try_into()?;
|
||||||
let doc = controller.open_view(params).await?;
|
let doc = controller.open_view(params).await?;
|
||||||
data_result(doc)
|
data_result(doc)
|
||||||
|
@ -15,7 +15,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use flowy_database::SqliteConnection;
|
use flowy_database::SqliteConnection;
|
||||||
use flowy_document::{
|
use flowy_document::{
|
||||||
entities::doc::{CreateDocParams, Doc, DocDelta, QueryDocParams},
|
entities::doc::{CreateDocParams, DocDelta, QueryDocParams},
|
||||||
module::FlowyDocument,
|
module::FlowyDocument,
|
||||||
};
|
};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@ -56,8 +56,7 @@ impl ViewController {
|
|||||||
// TODO: rollback anything created before if failed?
|
// TODO: rollback anything created before if failed?
|
||||||
conn.immediate_transaction::<_, WorkspaceError, _>(|| {
|
conn.immediate_transaction::<_, WorkspaceError, _>(|| {
|
||||||
let _ = self.save_view(view.clone(), conn)?;
|
let _ = self.save_view(view.clone(), conn)?;
|
||||||
self.document
|
self.document.create(CreateDocParams::new(&view.id, params.data))?;
|
||||||
.create(CreateDocParams::new(&view.id, params.data), conn)?;
|
|
||||||
|
|
||||||
let repeated_view = self.read_local_views_belong_to(&view.belong_to_id, conn)?;
|
let repeated_view = self.read_local_views_belong_to(&view.belong_to_id, conn)?;
|
||||||
dart_notify(&view.belong_to_id, WorkspaceObservable::AppCreateView)
|
dart_notify(&view.belong_to_id, WorkspaceObservable::AppCreateView)
|
||||||
@ -84,9 +83,9 @@ impl ViewController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(level = "debug", skip(self), err)]
|
#[tracing::instrument(level = "debug", skip(self), err)]
|
||||||
pub(crate) async fn open_view(&self, params: QueryDocParams) -> Result<Doc, WorkspaceError> {
|
pub(crate) async fn open_view(&self, params: QueryDocParams) -> Result<DocDelta, WorkspaceError> {
|
||||||
let edit_context = self.document.open(params, self.database.db_pool()?).await?;
|
let edit_context = self.document.open(params, self.database.db_pool()?).await?;
|
||||||
Ok(edit_context.doc().await.map_err(internal_error)?)
|
Ok(edit_context.delta().await.map_err(internal_error)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn delete_view(&self, params: DeleteViewParams) -> Result<(), WorkspaceError> {
|
pub(crate) async fn delete_view(&self, params: DeleteViewParams) -> Result<(), WorkspaceError> {
|
||||||
@ -95,7 +94,7 @@ impl ViewController {
|
|||||||
|
|
||||||
conn.immediate_transaction::<_, WorkspaceError, _>(|| {
|
conn.immediate_transaction::<_, WorkspaceError, _>(|| {
|
||||||
let view_table = self.sql.delete_view(¶ms.view_id, conn)?;
|
let view_table = self.sql.delete_view(¶ms.view_id, conn)?;
|
||||||
let _ = self.document.delete(params.into(), conn)?;
|
let _ = self.document.delete(params.into())?;
|
||||||
|
|
||||||
let repeated_view = self.read_local_views_belong_to(&view_table.belong_to_id, conn)?;
|
let repeated_view = self.read_local_views_belong_to(&view_table.belong_to_id, conn)?;
|
||||||
dart_notify(&view_table.belong_to_id, WorkspaceObservable::AppDeleteView)
|
dart_notify(&view_table.belong_to_id, WorkspaceObservable::AppDeleteView)
|
||||||
@ -134,7 +133,7 @@ impl ViewController {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn apply_doc_delta(&self, params: DocDelta) -> Result<Doc, WorkspaceError> {
|
pub(crate) async fn apply_doc_delta(&self, params: DocDelta) -> Result<DocDelta, WorkspaceError> {
|
||||||
let doc = self.document.apply_doc_delta(params).await?;
|
let doc = self.document.apply_doc_delta(params).await?;
|
||||||
Ok(doc)
|
Ok(doc)
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use dashmap::DashMap;
|
use dashmap::DashMap;
|
||||||
use flowy_infra::retry::{Action, ExponentialBackoff, FixedInterval, Retry};
|
use flowy_infra::retry::{Action, FixedInterval, Retry};
|
||||||
use flowy_net::errors::ServerError;
|
use flowy_net::errors::ServerError;
|
||||||
use futures_channel::mpsc::{UnboundedReceiver, UnboundedSender};
|
use futures_channel::mpsc::{UnboundedReceiver, UnboundedSender};
|
||||||
use futures_core::{ready, Stream};
|
use futures_core::{ready, Stream};
|
||||||
|
10
scripts/makefile/docker.toml
Normal file
10
scripts/makefile/docker.toml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
[tasks.show_usage]
|
||||||
|
script = """
|
||||||
|
docker system df -v
|
||||||
|
# docker volume rm xxxxx
|
||||||
|
docker volume prune
|
||||||
|
"""
|
||||||
|
|
||||||
|
#docker container ls -al
|
||||||
|
#docker stop clever_mayer
|
||||||
|
#docker rm clever_mayer
|
Loading…
Reference in New Issue
Block a user