菜单

数据库与协作系统

相关源文件

本文档解释了 AppFlowy 数据库系统的架构和实现,以及支撑其运行的实时协作功能。它涵盖了负责管理数据库操作、同步以及实现用户间实时协作的核心组件。

有关文档编辑的具体信息,请参阅文档编辑器系统,以及有关网格(Grid)、看板(Board)和日历(Calendar)等数据库视图的详细信息,请参阅视图和文档管理

概述

AppFlowy 的数据库和协作系统提供了一个框架,用于在不同设备上创建、管理和同步结构化数据。该系统旨在支持在线和离线工作,并在恢复连接时实现无缝同步。它支持多种数据库布局(网格、看板、日历),并支持实时协作编辑。

数据库和协作系统架构

来源

数据库系统架构

数据库系统围绕着一个分层架构进行组织,该架构管理数据库对象的创建、检索和操作。

核心组件

DatabaseManager 结构和关系

来源

关键类和职责

组件职责关键方法
DatabaseManager核心数据库注册和生命周期管理initialize(), get_database_editor_with_view_id(), open_database(), close_database_view()
DatabaseEditor数据库特定操作和协作设置open_database_view(), create_field_with_type_option(), update_field_type_option(), switch_to_field_type()
DatabaseViews数据库视图编辑器注册表get_or_init_view_editor(), remove_view(), num_editors()
DatabaseViewEditor视图特定数据处理和 UI 状态v_get_all_rows(), v_filter_rows(), v_will_create_row(), v_move_group_row()

DatabaseManager 生命周期管理

DatabaseManagerMutex<DatabaseEditorMap> 中维护数据库编辑器并实现仔细的清理逻辑

  • 活动编辑器存储在 editors: Mutex<DatabaseEditorMap>
  • 正在移除的编辑器存储在 removing_editor: Arc<Mutex<HashMap<String, Arc<DatabaseEditor>>>>
  • 通过 tokio::spawn 任务在 120 秒不活动后自动清理
  • WorkspaceDatabaseManager 处理工作区级别的数据库索引和元数据

DatabaseEditor 协作集成

每个 DatabaseEditor 通过以下方式与协作系统集成:

  • collab_builder: Weak<AppFlowyCollabBuilder> 用于创建协作对象
  • finalized_rows: Arc<moka::future::Cache<String, Weak<RwLock<DatabaseRow>>>> 用于行级协作
  • is_loading_rows: ArcSwapOption<broadcast::Sender<()>> 用于协调异步行加载
  • opening_ret_txs: Arc<RwLock<Vec<OpenDatabaseResult>>> 用于管理并发的数据库打开操作

DatabaseViewEditor 控制器架构

DatabaseViewEditor 协调多个专门的控制器

  • filter_controller: Arc<FilterController> - 处理行过滤逻辑
  • sort_controller: Arc<RwLock<SortController>> - 管理行排序
  • group_controller: Arc<RwLock<Option<Box<dyn GroupController>>>> - 可选的行分组
  • calculations_controller: Arc<CalculationsController> - 字段计算和聚合
  • row_orders: RwLock<Vec<RowOrder>> - 为视图缓存行顺序
  • row_by_row_id: DashMap<String, Arc<Row>> - 快速行查找缓存

来源

数据库数据模型

数据库系统围绕几个关键实体构建

来源

  • frontend/rust-lib/flowy-database2/src/services/database/database_editor.rs
  • frontend/rust-lib/flowy-database2/src/entities/row_entities.rs

协作框架

AppFlowy 的协作框架通过管理用户之间更改的同步,实现实时协作编辑。它建立在 CRDT(无冲突复制数据类型)基础之上,可以一致地合并来自多个用户的更改。

架构

AppFlowyCollabBuilder 集成和插件系统

来源

关键组件

AppFlowyCollabBuilder 配置

AppFlowyCollabBuilder 通过几个关键组件协调协作:

组件类型目的
network_reachabilityCollabConnectReachability跟踪网络连接状态以进行同步决策
plugin_providerArcSwap<Arc<dyn CollabCloudPluginProvider>>可切换的云插件提供商(本地 vs AppFlowy Cloud)
snapshot_persistenceArcSwapOption<Arc<dyn SnapshotPersistence>>可选的协作历史快照存储
workspace_integrateArc<dyn WorkspaceCollabIntegrate>工作区 ID 和设备 ID 管理
embeddings_writerOption<Weak<InstantIndexedDataWriter>>用于搜索索引的可选 AI 嵌入

CollabObject 生命周期

通过 collab_object() 方法创建 CollabObject

workspace_id validation → device_id retrieval → CollabObject construction

该方法验证工作区一致性并构造具有以下属性的对象:

  • uid: i64 - 用户标识符
  • object_id: String - 唯一对象标识符
  • collab_type: CollabType - 类型(Database, Document, Folder, etc.)
  • workspace_id: String - 工作区上下文
  • device_id: String - 用于冲突解决的设备标识

插件系统架构

finalize() 方法根据提供者类型配置插件

  • 本地模式:无云插件,仅通过 RocksdbDiskPlugin 进行本地存储
  • AppFlowy 云模式:从 CollabCloudPluginProvider 添加云同步插件
  • 插件配置:在 collab.initialize() 之前通过 collab.add_plugin() 添加插件

存储插件使用 CollabPersistenceConfig 通过 RocksdbDiskPluginIndexeddbDiskPlugin 进行本地持久化。

来源

同步流程

实时协作流程

数据持久化架构

系统实现多层持久化

  1. 即时本地持久化RocksdbDiskPlugin 使用 KVTransactionDB 写入 CollabKVDB
  2. 冲突解决:CRDT 算法确保客户端之间的一致状态
  3. 快照管理:可选的 SnapshotPersistence 用于协作历史记录
  4. 云同步WSClient 通过 WebSocketChannel<ServerCollabMessage> 管理实时同步

DatabaseEditor.finalized_rows 缓存(moka::future::Cache)提供行级协作,并具有自动驱逐和清理功能。

来源

数据库操作

数据库系统提供了一套全面的操作,用于管理数据库、视图、字段和行。以下是关键操作及其实现概述。

数据库 CRUD 操作

数据库操作主要由 DatabaseManager 类处理

来源

  • frontend/rust-lib/flowy-database2/src/manager.rs:67-567

字段操作

字段操作由 DatabaseEditor 类处理

来源

  • frontend/rust-lib/flowy-database2/src/services/database/database_editor.rs:381-393
  • frontend/rust-lib/flowy-database2/src/services/database/database_editor.rs:463-482
  • frontend/rust-lib/flowy-database2/src/services/database/database_editor.rs:484-533

行操作

行操作也由 DatabaseEditor 类处理

来源

  • frontend/rust-lib/flowy-database2/src/services/database/database_editor.rs:776-786
  • frontend/rust-lib/flowy-database2/src/services/database/database_editor.rs:679-701

视图操作

视图操作通过 DatabaseViewEditor 类管理

来源

  • frontend/rust-lib/flowy-database2/src/services/database_view/view_editor.rs:403-411
  • frontend/rust-lib/flowy-database2/src/services/database_view/view_editor.rs:437-459

服务器集成

数据库和协作系统根据用户的配置与不同的服务器实现集成。

服务器架构

来源

  • frontend/rust-lib/flowy-server/src/server.rs:42-95
  • frontend/rust-lib/flowy-server/src/af_cloud/server.rs:48-66
  • frontend/rust-lib/flowy-server/src/local_server/server.rs:20-33

云同步

使用 AppFlowy 云时,数据库更改通过 WebSocket 通道同步

来源

  • frontend/rust-lib/flowy-server/src/af_cloud/server.rs:290-309

数据持久化架构

本地存储架构

协作系统使用 SQLite 存储元数据,使用 RocksDB/IndexedDB 存储协作数据

本地数据库架构

存储插件架构

CollabKVDB 存储集成

缓存管理

系统通过以下方式实现复杂的缓存:

  • 行缓存DatabaseEditor.finalized_rows 使用 moka::future::Cache<String, Weak<RwLock<DatabaseRow>>>
  • 单元格缓存CellCacheAnyTypeCache<u64> 的类型别名)用于类型化的单元格数据
  • 视图缓存DatabaseViews.editor_by_view_id 用于视图编辑器实例
  • 驱逐处理database_row_evict_listener() 用于缓存驱逐时的清理

缓存配置包括

  • 行缓存最大容量为 50 条
  • 用于正确清理的异步驱逐监听器
  • 弱引用以防止内存泄漏

来源

数据库系统中的数据流

通过数据库和协作层的完整数据流

事件处理流程

步骤组件方法目的
1事件处理器upgrade_manager()验证 DatabaseManager 的可用性
2DatabaseManagerget_database_editor_with_view_id()检索或创建 DatabaseEditor
3DatabaseManageropen_database()使用重试逻辑初始化数据库
4DatabaseEditoropen_database_view()创建视图特定编辑器和控制器
5DatabaseViewEditorv_filter_rows(), v_sort_rows()通过视图控制器处理数据
6AppFlowyCollabBuilderfinalize()配置协作插件
7协作插件存储/同步将更改持久化到本地和云端

错误处理和恢复

系统实现全面的错误处理

  • 管理器级别FlowyResult<Arc<DatabaseEditor>> 带有重试机制
  • 编辑器级别opening_ret_txs 用于协调并发打开操作
  • 视图级别:可选控制器处理优雅降级
  • 协作级别:通过 CollabConnectReachability 进行网络状态跟踪

来源

事件处理

数据库操作通过事件系统触发,该系统将前端请求映射到后端处理器

来源

  • frontend/rust-lib/flowy-database2/src/event_map.rs:11-105
  • frontend/rust-lib/flowy-database2/src/event_handler.rs:31-54

结论

AppFlowy 中的数据库和协作系统为创建、管理和同步结构化数据提供了强大的基础。通过将灵活的数据库模型与实时协作功能相结合,它使用户能够跨设备和网络条件无缝地在数据库上协同工作。

该系统在设计时考虑了模块化,将数据库管理、视图呈现和协作之间的关注点分离,使其具有可扩展性和可维护性。与本地存储和云服务的集成确保了数据持久性和同步,同时保持了离线功能。