diff --git a/frontend/appflowy_flutter/lib/plugins/document/application/editor_transaction_adapter.dart b/frontend/appflowy_flutter/lib/plugins/document/application/editor_transaction_adapter.dart index 172c3b2bc9..1038bea043 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/application/editor_transaction_adapter.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/application/editor_transaction_adapter.dart @@ -22,6 +22,7 @@ import 'package:appflowy_editor/appflowy_editor.dart' blockComponentDelta; import 'package:collection/collection.dart'; import 'package:nanoid/nanoid.dart'; +import 'package:synchronized/synchronized.dart'; const _kExternalTextType = 'text'; @@ -38,7 +39,33 @@ class TransactionAdapter { final DocumentService documentService; final String documentId; + // Controls the apply transaction flow + // + // Ensures transactions are applied in the correct order when dependencies exist. + // Example: If transaction B depends on transaction A, A must be applied first. + final Lock _applyLock = Lock(); + Future apply(Transaction transaction, EditorState editorState) async { + await _applyLock.synchronized( + () async { + if (enableDocumentInternalLog) { + Log.debug('apply transaction begin ${transaction.hashCode}'); + } + + await _applyInternal(transaction, editorState); + + if (enableDocumentInternalLog) { + Log.debug('apply transaction end ${transaction.hashCode}'); + } + }, + timeout: const Duration(seconds: 5), + ); + } + + Future _applyInternal( + Transaction transaction, + EditorState editorState, + ) async { final stopwatch = Stopwatch()..start(); if (enableDocumentInternalLog) { Log.debug('transaction => ${transaction.toJson()}'); diff --git a/frontend/appflowy_flutter/macos/Podfile.lock b/frontend/appflowy_flutter/macos/Podfile.lock index 525eb1e347..f47e41d141 100644 --- a/frontend/appflowy_flutter/macos/Podfile.lock +++ b/frontend/appflowy_flutter/macos/Podfile.lock @@ -142,7 +142,7 @@ SPEC CHECKSUMS: HotKey: e96d8a2ddbf4591131e2bb3f54e69554d90cdca6 hotkey_manager: c32bf0bfe8f934b7bc17ab4ad5c4c142960b023c irondash_engine_context: da62996ee25616d2f01bbeb85dc115d813359478 - local_notifier: c6c371695f914641ab7bc8601944f7e358632d0b + local_notifier: e9506bc66fc70311e8bc7291fb70f743c081e4ff package_info_plus: fa739dd842b393193c5ca93c26798dff6e3d0e0c path_provider_foundation: 3784922295ac71e43754bd15e0653ccfd36a147c ReachabilitySwift: 7f151ff156cea1481a8411701195ac6a984f4979 diff --git a/frontend/appflowy_flutter/pubspec.lock b/frontend/appflowy_flutter/pubspec.lock index 7c27e51401..c28cc50973 100644 --- a/frontend/appflowy_flutter/pubspec.lock +++ b/frontend/appflowy_flutter/pubspec.lock @@ -2059,7 +2059,7 @@ packages: source: hosted version: "0.3.1" synchronized: - dependency: transitive + dependency: "direct main" description: name: synchronized sha256: "539ef412b170d65ecdafd780f924e5be3f60032a1128df156adad6c5b373d558" diff --git a/frontend/appflowy_flutter/pubspec.yaml b/frontend/appflowy_flutter/pubspec.yaml index 7e6633e9d4..d0fe131746 100644 --- a/frontend/appflowy_flutter/pubspec.yaml +++ b/frontend/appflowy_flutter/pubspec.yaml @@ -157,6 +157,7 @@ dependencies: # Used to open local files on Mobile open_filex: ^4.5.0 + synchronized: ^3.1.0+1 dev_dependencies: flutter_lints: ^4.0.0