chore: fix lib dispatch (#6008)

* chore: replace rc with arc

* chore: fix dispatch

* chore: fix test

* chore: fix dispatch

* chore: fix test

* chore: remove afconcurrent

* chore: fix runtime block_on runtime
This commit is contained in:
Nathan.fooo 2024-08-19 22:08:10 +08:00 committed by GitHub
parent 7113269802
commit 58b17a939c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
24 changed files with 370 additions and 369 deletions

View File

@ -963,7 +963,7 @@ dependencies = [
[[package]] [[package]]
name = "collab" name = "collab"
version = "0.2.0" version = "0.2.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=2ba00c1e430f6157a2b6cbda89992d3b154ea6fb#2ba00c1e430f6157a2b6cbda89992d3b154ea6fb" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b0cd69ec92a42a319a1fdb2e184151162db52cd6#b0cd69ec92a42a319a1fdb2e184151162db52cd6"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"arc-swap", "arc-swap",
@ -988,7 +988,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-database" name = "collab-database"
version = "0.2.0" version = "0.2.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=2ba00c1e430f6157a2b6cbda89992d3b154ea6fb#2ba00c1e430f6157a2b6cbda89992d3b154ea6fb" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b0cd69ec92a42a319a1fdb2e184151162db52cd6#b0cd69ec92a42a319a1fdb2e184151162db52cd6"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-trait", "async-trait",
@ -1018,7 +1018,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-document" name = "collab-document"
version = "0.2.0" version = "0.2.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=2ba00c1e430f6157a2b6cbda89992d3b154ea6fb#2ba00c1e430f6157a2b6cbda89992d3b154ea6fb" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b0cd69ec92a42a319a1fdb2e184151162db52cd6#b0cd69ec92a42a319a1fdb2e184151162db52cd6"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"arc-swap", "arc-swap",
@ -1038,7 +1038,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-entity" name = "collab-entity"
version = "0.2.0" version = "0.2.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=2ba00c1e430f6157a2b6cbda89992d3b154ea6fb#2ba00c1e430f6157a2b6cbda89992d3b154ea6fb" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b0cd69ec92a42a319a1fdb2e184151162db52cd6#b0cd69ec92a42a319a1fdb2e184151162db52cd6"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bytes", "bytes",
@ -1057,7 +1057,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-folder" name = "collab-folder"
version = "0.2.0" version = "0.2.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=2ba00c1e430f6157a2b6cbda89992d3b154ea6fb#2ba00c1e430f6157a2b6cbda89992d3b154ea6fb" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b0cd69ec92a42a319a1fdb2e184151162db52cd6#b0cd69ec92a42a319a1fdb2e184151162db52cd6"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"arc-swap", "arc-swap",
@ -1100,7 +1100,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-plugins" name = "collab-plugins"
version = "0.2.0" version = "0.2.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=2ba00c1e430f6157a2b6cbda89992d3b154ea6fb#2ba00c1e430f6157a2b6cbda89992d3b154ea6fb" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b0cd69ec92a42a319a1fdb2e184151162db52cd6#b0cd69ec92a42a319a1fdb2e184151162db52cd6"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-stream", "async-stream",
@ -1180,7 +1180,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-user" name = "collab-user"
version = "0.2.0" version = "0.2.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=2ba00c1e430f6157a2b6cbda89992d3b154ea6fb#2ba00c1e430f6157a2b6cbda89992d3b154ea6fb" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b0cd69ec92a42a319a1fdb2e184151162db52cd6#b0cd69ec92a42a319a1fdb2e184151162db52cd6"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"collab", "collab",

View File

@ -116,13 +116,13 @@ custom-protocol = ["tauri/custom-protocol"]
# To switch to the local path, run: # To switch to the local path, run:
# scripts/tool/update_collab_source.sh # scripts/tool/update_collab_source.sh
# ⚠️⚠️⚠️️ # ⚠️⚠️⚠️️
collab = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "2ba00c1e430f6157a2b6cbda89992d3b154ea6fb" } collab = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "b0cd69ec92a42a319a1fdb2e184151162db52cd6" }
collab-entity = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "2ba00c1e430f6157a2b6cbda89992d3b154ea6fb" } collab-entity = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "b0cd69ec92a42a319a1fdb2e184151162db52cd6" }
collab-folder = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "2ba00c1e430f6157a2b6cbda89992d3b154ea6fb" } collab-folder = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "b0cd69ec92a42a319a1fdb2e184151162db52cd6" }
collab-document = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "2ba00c1e430f6157a2b6cbda89992d3b154ea6fb" } collab-document = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "b0cd69ec92a42a319a1fdb2e184151162db52cd6" }
collab-database = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "2ba00c1e430f6157a2b6cbda89992d3b154ea6fb" } collab-database = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "b0cd69ec92a42a319a1fdb2e184151162db52cd6" }
collab-plugins = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "2ba00c1e430f6157a2b6cbda89992d3b154ea6fb" } collab-plugins = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "b0cd69ec92a42a319a1fdb2e184151162db52cd6" }
collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "2ba00c1e430f6157a2b6cbda89992d3b154ea6fb" } collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "b0cd69ec92a42a319a1fdb2e184151162db52cd6" }
# Working directory: frontend # Working directory: frontend
# To update the commit ID, run: # To update the commit ID, run:

View File

@ -2,7 +2,6 @@ use dotenv::dotenv;
use flowy_core::config::AppFlowyCoreConfig; use flowy_core::config::AppFlowyCoreConfig;
use flowy_core::{AppFlowyCore, DEFAULT_NAME}; use flowy_core::{AppFlowyCore, DEFAULT_NAME};
use lib_dispatch::runtime::AFPluginRuntime; use lib_dispatch::runtime::AFPluginRuntime;
use std::rc::Rc;
use std::sync::Mutex; use std::sync::Mutex;
pub fn read_env() { pub fn read_env() {
@ -61,18 +60,18 @@ pub(crate) fn init_appflowy_core() -> MutexAppFlowyCore {
) )
.log_filter("trace", vec!["appflowy_tauri".to_string()]); .log_filter("trace", vec!["appflowy_tauri".to_string()]);
let runtime = Rc::new(AFPluginRuntime::new().unwrap()); let runtime = Arc::new(AFPluginRuntime::new().unwrap());
let cloned_runtime = runtime.clone(); let cloned_runtime = runtime.clone();
runtime.block_on(async move { runtime.block_on(async move {
MutexAppFlowyCore::new(AppFlowyCore::new(config, cloned_runtime, None).await) MutexAppFlowyCore::new(AppFlowyCore::new(config, cloned_runtime, None).await)
}) })
} }
pub struct MutexAppFlowyCore(pub Rc<Mutex<AppFlowyCore>>); pub struct MutexAppFlowyCore(pub Arc<Mutex<AppFlowyCore>>);
impl MutexAppFlowyCore { impl MutexAppFlowyCore {
fn new(appflowy_core: AppFlowyCore) -> Self { fn new(appflowy_core: AppFlowyCore) -> Self {
Self(Rc::new(Mutex::new(appflowy_core))) Self(Arc::new(Mutex::new(appflowy_core)))
} }
} }
unsafe impl Sync for MutexAppFlowyCore {} unsafe impl Sync for MutexAppFlowyCore {}

View File

@ -946,7 +946,7 @@ dependencies = [
[[package]] [[package]]
name = "collab" name = "collab"
version = "0.2.0" version = "0.2.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=2ba00c1e430f6157a2b6cbda89992d3b154ea6fb#2ba00c1e430f6157a2b6cbda89992d3b154ea6fb" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b0cd69ec92a42a319a1fdb2e184151162db52cd6#b0cd69ec92a42a319a1fdb2e184151162db52cd6"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"arc-swap", "arc-swap",
@ -971,7 +971,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-database" name = "collab-database"
version = "0.2.0" version = "0.2.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=2ba00c1e430f6157a2b6cbda89992d3b154ea6fb#2ba00c1e430f6157a2b6cbda89992d3b154ea6fb" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b0cd69ec92a42a319a1fdb2e184151162db52cd6#b0cd69ec92a42a319a1fdb2e184151162db52cd6"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-trait", "async-trait",
@ -1001,7 +1001,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-document" name = "collab-document"
version = "0.2.0" version = "0.2.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=2ba00c1e430f6157a2b6cbda89992d3b154ea6fb#2ba00c1e430f6157a2b6cbda89992d3b154ea6fb" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b0cd69ec92a42a319a1fdb2e184151162db52cd6#b0cd69ec92a42a319a1fdb2e184151162db52cd6"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"arc-swap", "arc-swap",
@ -1021,7 +1021,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-entity" name = "collab-entity"
version = "0.2.0" version = "0.2.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=2ba00c1e430f6157a2b6cbda89992d3b154ea6fb#2ba00c1e430f6157a2b6cbda89992d3b154ea6fb" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b0cd69ec92a42a319a1fdb2e184151162db52cd6#b0cd69ec92a42a319a1fdb2e184151162db52cd6"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bytes", "bytes",
@ -1040,7 +1040,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-folder" name = "collab-folder"
version = "0.2.0" version = "0.2.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=2ba00c1e430f6157a2b6cbda89992d3b154ea6fb#2ba00c1e430f6157a2b6cbda89992d3b154ea6fb" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b0cd69ec92a42a319a1fdb2e184151162db52cd6#b0cd69ec92a42a319a1fdb2e184151162db52cd6"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"arc-swap", "arc-swap",
@ -1083,7 +1083,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-plugins" name = "collab-plugins"
version = "0.2.0" version = "0.2.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=2ba00c1e430f6157a2b6cbda89992d3b154ea6fb#2ba00c1e430f6157a2b6cbda89992d3b154ea6fb" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b0cd69ec92a42a319a1fdb2e184151162db52cd6#b0cd69ec92a42a319a1fdb2e184151162db52cd6"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-stream", "async-stream",
@ -1163,7 +1163,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-user" name = "collab-user"
version = "0.2.0" version = "0.2.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=2ba00c1e430f6157a2b6cbda89992d3b154ea6fb#2ba00c1e430f6157a2b6cbda89992d3b154ea6fb" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b0cd69ec92a42a319a1fdb2e184151162db52cd6#b0cd69ec92a42a319a1fdb2e184151162db52cd6"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"collab", "collab",

View File

@ -116,13 +116,13 @@ custom-protocol = ["tauri/custom-protocol"]
# To switch to the local path, run: # To switch to the local path, run:
# scripts/tool/update_collab_source.sh # scripts/tool/update_collab_source.sh
# ⚠️⚠️⚠️️ # ⚠️⚠️⚠️️
collab = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "2ba00c1e430f6157a2b6cbda89992d3b154ea6fb" } collab = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "b0cd69ec92a42a319a1fdb2e184151162db52cd6" }
collab-entity = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "2ba00c1e430f6157a2b6cbda89992d3b154ea6fb" } collab-entity = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "b0cd69ec92a42a319a1fdb2e184151162db52cd6" }
collab-folder = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "2ba00c1e430f6157a2b6cbda89992d3b154ea6fb" } collab-folder = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "b0cd69ec92a42a319a1fdb2e184151162db52cd6" }
collab-document = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "2ba00c1e430f6157a2b6cbda89992d3b154ea6fb" } collab-document = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "b0cd69ec92a42a319a1fdb2e184151162db52cd6" }
collab-database = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "2ba00c1e430f6157a2b6cbda89992d3b154ea6fb" } collab-database = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "b0cd69ec92a42a319a1fdb2e184151162db52cd6" }
collab-plugins = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "2ba00c1e430f6157a2b6cbda89992d3b154ea6fb" } collab-plugins = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "b0cd69ec92a42a319a1fdb2e184151162db52cd6" }
collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "2ba00c1e430f6157a2b6cbda89992d3b154ea6fb" } collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "b0cd69ec92a42a319a1fdb2e184151162db52cd6" }
# Working directory: frontend # Working directory: frontend
# To update the commit ID, run: # To update the commit ID, run:

View File

@ -3,7 +3,7 @@ use flowy_core::config::AppFlowyCoreConfig;
use flowy_core::{AppFlowyCore, DEFAULT_NAME}; use flowy_core::{AppFlowyCore, DEFAULT_NAME};
use lib_dispatch::runtime::AFPluginRuntime; use lib_dispatch::runtime::AFPluginRuntime;
use std::rc::Rc; use std::rc::Rc;
use std::sync::Mutex; use std::sync::{Arc, Mutex};
pub fn read_env() { pub fn read_env() {
dotenv().ok(); dotenv().ok();
@ -61,18 +61,18 @@ pub fn init_appflowy_core() -> MutexAppFlowyCore {
) )
.log_filter("trace", vec!["appflowy_tauri".to_string()]); .log_filter("trace", vec!["appflowy_tauri".to_string()]);
let runtime = Rc::new(AFPluginRuntime::new().unwrap()); let runtime = Arc::new(AFPluginRuntime::new().unwrap());
let cloned_runtime = runtime.clone(); let cloned_runtime = runtime.clone();
runtime.block_on(async move { runtime.block_on(async move {
MutexAppFlowyCore::new(AppFlowyCore::new(config, cloned_runtime, None).await) MutexAppFlowyCore::new(AppFlowyCore::new(config, cloned_runtime, None).await)
}) })
} }
pub struct MutexAppFlowyCore(pub Rc<Mutex<AppFlowyCore>>); pub struct MutexAppFlowyCore(pub Arc<Mutex<AppFlowyCore>>);
impl MutexAppFlowyCore { impl MutexAppFlowyCore {
pub(crate) fn new(appflowy_core: AppFlowyCore) -> Self { pub(crate) fn new(appflowy_core: AppFlowyCore) -> Self {
Self(Rc::new(Mutex::new(appflowy_core))) Self(Arc::new(Mutex::new(appflowy_core)))
} }
} }
unsafe impl Sync for MutexAppFlowyCore {} unsafe impl Sync for MutexAppFlowyCore {}

View File

@ -824,7 +824,7 @@ dependencies = [
[[package]] [[package]]
name = "collab" name = "collab"
version = "0.2.0" version = "0.2.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=2ba00c1e430f6157a2b6cbda89992d3b154ea6fb#2ba00c1e430f6157a2b6cbda89992d3b154ea6fb" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b0cd69ec92a42a319a1fdb2e184151162db52cd6#b0cd69ec92a42a319a1fdb2e184151162db52cd6"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"arc-swap", "arc-swap",
@ -849,7 +849,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-database" name = "collab-database"
version = "0.2.0" version = "0.2.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=2ba00c1e430f6157a2b6cbda89992d3b154ea6fb#2ba00c1e430f6157a2b6cbda89992d3b154ea6fb" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b0cd69ec92a42a319a1fdb2e184151162db52cd6#b0cd69ec92a42a319a1fdb2e184151162db52cd6"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-trait", "async-trait",
@ -879,7 +879,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-document" name = "collab-document"
version = "0.2.0" version = "0.2.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=2ba00c1e430f6157a2b6cbda89992d3b154ea6fb#2ba00c1e430f6157a2b6cbda89992d3b154ea6fb" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b0cd69ec92a42a319a1fdb2e184151162db52cd6#b0cd69ec92a42a319a1fdb2e184151162db52cd6"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"arc-swap", "arc-swap",
@ -899,7 +899,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-entity" name = "collab-entity"
version = "0.2.0" version = "0.2.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=2ba00c1e430f6157a2b6cbda89992d3b154ea6fb#2ba00c1e430f6157a2b6cbda89992d3b154ea6fb" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b0cd69ec92a42a319a1fdb2e184151162db52cd6#b0cd69ec92a42a319a1fdb2e184151162db52cd6"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bytes", "bytes",
@ -918,7 +918,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-folder" name = "collab-folder"
version = "0.2.0" version = "0.2.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=2ba00c1e430f6157a2b6cbda89992d3b154ea6fb#2ba00c1e430f6157a2b6cbda89992d3b154ea6fb" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b0cd69ec92a42a319a1fdb2e184151162db52cd6#b0cd69ec92a42a319a1fdb2e184151162db52cd6"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"arc-swap", "arc-swap",
@ -961,7 +961,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-plugins" name = "collab-plugins"
version = "0.2.0" version = "0.2.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=2ba00c1e430f6157a2b6cbda89992d3b154ea6fb#2ba00c1e430f6157a2b6cbda89992d3b154ea6fb" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b0cd69ec92a42a319a1fdb2e184151162db52cd6#b0cd69ec92a42a319a1fdb2e184151162db52cd6"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-stream", "async-stream",
@ -1041,7 +1041,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-user" name = "collab-user"
version = "0.2.0" version = "0.2.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=2ba00c1e430f6157a2b6cbda89992d3b154ea6fb#2ba00c1e430f6157a2b6cbda89992d3b154ea6fb" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b0cd69ec92a42a319a1fdb2e184151162db52cd6#b0cd69ec92a42a319a1fdb2e184151162db52cd6"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"collab", "collab",
@ -1325,6 +1325,7 @@ dependencies = [
"flowy-server", "flowy-server",
"flowy-server-pub", "flowy-server-pub",
"flowy-user", "flowy-user",
"futures",
"lazy_static", "lazy_static",
"lib-dispatch", "lib-dispatch",
"lib-log", "lib-log",

View File

@ -136,13 +136,13 @@ rocksdb = { git = "https://github.com/rust-rocksdb/rust-rocksdb", rev = "1710120
# To switch to the local path, run: # To switch to the local path, run:
# scripts/tool/update_collab_source.sh # scripts/tool/update_collab_source.sh
# ⚠️⚠️⚠️️ # ⚠️⚠️⚠️️
collab = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "2ba00c1e430f6157a2b6cbda89992d3b154ea6fb" } collab = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "b0cd69ec92a42a319a1fdb2e184151162db52cd6" }
collab-entity = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "2ba00c1e430f6157a2b6cbda89992d3b154ea6fb" } collab-entity = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "b0cd69ec92a42a319a1fdb2e184151162db52cd6" }
collab-folder = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "2ba00c1e430f6157a2b6cbda89992d3b154ea6fb" } collab-folder = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "b0cd69ec92a42a319a1fdb2e184151162db52cd6" }
collab-document = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "2ba00c1e430f6157a2b6cbda89992d3b154ea6fb" } collab-document = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "b0cd69ec92a42a319a1fdb2e184151162db52cd6" }
collab-database = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "2ba00c1e430f6157a2b6cbda89992d3b154ea6fb" } collab-database = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "b0cd69ec92a42a319a1fdb2e184151162db52cd6" }
collab-plugins = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "2ba00c1e430f6157a2b6cbda89992d3b154ea6fb" } collab-plugins = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "b0cd69ec92a42a319a1fdb2e184151162db52cd6" }
collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "2ba00c1e430f6157a2b6cbda89992d3b154ea6fb" } collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "b0cd69ec92a42a319a1fdb2e184151162db52cd6" }
# Working directory: frontend # Working directory: frontend
# To update the commit ID, run: # To update the commit ID, run:

View File

@ -257,6 +257,7 @@ impl AppFlowyCollabBuilder {
{ {
let mut write_collab = collab.try_write()?; let mut write_collab = collab.try_write()?;
if !write_collab.borrow().get_state().is_uninitialized() { if !write_collab.borrow().get_state().is_uninitialized() {
warn!("{} is already initialized", object);
drop(write_collab); drop(write_collab);
return Ok(collab); return Ok(collab);
} }
@ -285,10 +286,7 @@ impl AppFlowyCollabBuilder {
} }
} }
if build_config.auto_initialize { (*write_collab).borrow_mut().initialize();
// at the moment when we get the lock, the collab object is not yet exposed outside
(*write_collab).borrow_mut().initialize();
}
drop(write_collab); drop(write_collab);
Ok(collab) Ok(collab)
} }
@ -296,19 +294,11 @@ impl AppFlowyCollabBuilder {
pub struct CollabBuilderConfig { pub struct CollabBuilderConfig {
pub sync_enable: bool, pub sync_enable: bool,
/// If auto_initialize is false, the collab object will not be initialized automatically.
/// You need to call collab.initialize() manually.
///
/// Default is true.
pub auto_initialize: bool,
} }
impl Default for CollabBuilderConfig { impl Default for CollabBuilderConfig {
fn default() -> Self { fn default() -> Self {
Self { Self { sync_enable: true }
sync_enable: true,
auto_initialize: true,
}
} }
} }
@ -317,11 +307,6 @@ impl CollabBuilderConfig {
self.sync_enable = sync_enable; self.sync_enable = sync_enable;
self self
} }
pub fn auto_initialize(mut self, auto_initialize: bool) -> Self {
self.auto_initialize = auto_initialize;
self
}
} }
pub struct KVDBCollabPersistenceImpl { pub struct KVDBCollabPersistenceImpl {

View File

@ -45,6 +45,7 @@ collab-integrate = { workspace = true }
flowy-derive.workspace = true flowy-derive.workspace = true
serde_yaml = "0.9.27" serde_yaml = "0.9.27"
flowy-error = { workspace = true, features = ["impl_from_sqlite", "impl_from_dispatch_error", "impl_from_appflowy_cloud", "impl_from_reqwest", "impl_from_serde", "dart"] } flowy-error = { workspace = true, features = ["impl_from_sqlite", "impl_from_dispatch_error", "impl_from_appflowy_cloud", "impl_from_reqwest", "impl_from_serde", "dart"] }
futures = "0.3.26"
[features] [features]
default = ["dart"] default = ["dart"]

View File

@ -3,9 +3,10 @@
use allo_isolate::Isolate; use allo_isolate::Isolate;
use lazy_static::lazy_static; use lazy_static::lazy_static;
use semver::Version; use semver::Version;
use std::rc::Rc; use std::sync::{mpsc, Arc, RwLock};
use std::sync::{Arc, Mutex};
use std::{ffi::CStr, os::raw::c_char}; use std::{ffi::CStr, os::raw::c_char};
use tokio::runtime::Builder;
use tokio::task::LocalSet;
use tracing::{debug, error, info, trace, warn}; use tracing::{debug, error, info, trace, warn};
use flowy_core::config::AppFlowyCoreConfig; use flowy_core::config::AppFlowyCoreConfig;
@ -33,34 +34,77 @@ mod notification;
mod protobuf; mod protobuf;
lazy_static! { lazy_static! {
static ref APPFLOWY_CORE: MutexAppFlowyCore = MutexAppFlowyCore::new(); static ref DART_APPFLOWY_CORE: DartAppFlowyCore = DartAppFlowyCore::new();
static ref LOG_STREAM_ISOLATE: Mutex<Option<Isolate>> = Mutex::new(None); static ref LOG_STREAM_ISOLATE: RwLock<Option<Isolate>> = RwLock::new(None);
} }
unsafe impl Send for MutexAppFlowyCore {} pub struct Task {
unsafe impl Sync for MutexAppFlowyCore {} dispatcher: Arc<AFPluginDispatcher>,
request: AFPluginRequest,
port: i64,
ret: Option<mpsc::Sender<DispatchFuture<AFPluginEventResponse>>>,
}
///FIXME: I'm pretty sure that there's a better way to do this unsafe impl Send for Task {}
struct MutexAppFlowyCore(Rc<Mutex<Option<AppFlowyCore>>>); unsafe impl Sync for DartAppFlowyCore {}
impl MutexAppFlowyCore { struct DartAppFlowyCore {
core: Arc<RwLock<Option<AppFlowyCore>>>,
handle: RwLock<Option<std::thread::JoinHandle<()>>>,
sender: RwLock<Option<mpsc::Sender<Task>>>,
}
impl DartAppFlowyCore {
fn new() -> Self { fn new() -> Self {
Self(Rc::new(Mutex::new(None))) Self {
core: Arc::new(RwLock::new(None)),
handle: RwLock::new(None),
sender: RwLock::new(None),
}
} }
fn dispatcher(&self) -> Option<Rc<AFPluginDispatcher>> { fn dispatcher(&self) -> Option<Arc<AFPluginDispatcher>> {
let binding = self.0.lock().unwrap(); let binding = self
.core
.read()
.expect("Failed to acquire read lock for core");
let core = binding.as_ref(); let core = binding.as_ref();
core.map(|core| core.event_dispatcher.clone()) core.map(|core| core.event_dispatcher.clone())
} }
fn dispatch(
&self,
request: AFPluginRequest,
port: i64,
ret: Option<mpsc::Sender<DispatchFuture<AFPluginEventResponse>>>,
) {
if let Ok(sender_guard) = self.sender.read() {
if let Err(e) = sender_guard.as_ref().unwrap().send(Task {
dispatcher: self.dispatcher().unwrap(),
request,
port,
ret,
}) {
error!("Failed to send task: {}", e);
}
} else {
warn!("Failed to acquire read lock for sender");
return;
}
}
} }
#[no_mangle] #[no_mangle]
pub extern "C" fn init_sdk(_port: i64, data: *mut c_char) -> i64 { pub extern "C" fn init_sdk(_port: i64, data: *mut c_char) -> i64 {
// and sent it the `Rust's` result let c_str = unsafe {
// no need to convert anything :) if data.is_null() {
let c_str = unsafe { CStr::from_ptr(data) }; return -1;
let serde_str = c_str.to_str().unwrap(); }
CStr::from_ptr(data)
};
let serde_str = c_str
.to_str()
.expect("Failed to convert C string to Rust string");
let configuration = AppFlowyDartConfiguration::from_str(serde_str); let configuration = AppFlowyDartConfiguration::from_str(serde_str);
configuration.write_env(); configuration.write_env();
@ -85,26 +129,49 @@ pub extern "C" fn init_sdk(_port: i64, data: *mut c_char) -> i64 {
DEFAULT_NAME.to_string(), DEFAULT_NAME.to_string(),
); );
// Ensure that the database is closed before initialization. Also, verify that the init_sdk function can be called if let Some(core) = &*DART_APPFLOWY_CORE.core.write().unwrap() {
// multiple times (is reentrant). Currently, only the database resource is exclusive.
if let Some(core) = &*APPFLOWY_CORE.0.lock().unwrap() {
core.close_db(); core.close_db();
} }
let runtime = Rc::new(AFPluginRuntime::new().unwrap());
let cloned_runtime = runtime.clone();
let log_stream = LOG_STREAM_ISOLATE let log_stream = LOG_STREAM_ISOLATE
.lock() .write()
.unwrap() .unwrap()
.take() .take()
.map(|isolate| Arc::new(LogStreamSenderImpl { isolate }) as Arc<dyn StreamLogSender>); .map(|isolate| Arc::new(LogStreamSenderImpl { isolate }) as Arc<dyn StreamLogSender>);
let (sender, task_rx) = mpsc::channel::<Task>();
let handle = std::thread::spawn(move || {
let local_set = LocalSet::new();
while let Ok(task) = task_rx.recv() {
let Task {
dispatcher,
request,
port,
ret,
} = task;
// let isolate = allo_isolate::Isolate::new(port); let resp = AFPluginDispatcher::boxed_async_send_with_callback(
*APPFLOWY_CORE.0.lock().unwrap() = runtime.block_on(async move { dispatcher.as_ref(),
Some(AppFlowyCore::new(config, cloned_runtime, log_stream).await) request,
// isolate.post("".to_string()); move |resp: AFPluginEventResponse| {
#[cfg(feature = "sync_verbose_log")]
trace!("[FFI]: Post data to dart through {} port", port);
Box::pin(post_to_flutter(resp, port))
},
&local_set,
);
if let Some(ret) = ret {
let _ = ret.send(resp);
}
}
}); });
*DART_APPFLOWY_CORE.sender.write().unwrap() = Some(sender);
*DART_APPFLOWY_CORE.handle.write().unwrap() = Some(handle);
let runtime = Arc::new(AFPluginRuntime::new().unwrap());
let cloned_runtime = runtime.clone();
*DART_APPFLOWY_CORE.core.write().unwrap() = runtime
.block_on(async move { Some(AppFlowyCore::new(config, cloned_runtime, log_stream).await) });
0 0
} }
@ -120,40 +187,13 @@ pub extern "C" fn async_event(port: i64, input: *const u8, len: usize) {
port port
); );
let dispatcher = match APPFLOWY_CORE.dispatcher() { DART_APPFLOWY_CORE.dispatch(request, port, None);
None => {
error!("sdk not init yet.");
return;
},
Some(dispatcher) => dispatcher,
};
AFPluginDispatcher::boxed_async_send_with_callback(
dispatcher.as_ref(),
request,
move |resp: AFPluginEventResponse| {
#[cfg(feature = "sync_verbose_log")]
trace!("[FFI]: Post data to dart through {} port", port);
Box::pin(post_to_flutter(resp, port))
},
);
} }
#[no_mangle] #[no_mangle]
pub extern "C" fn sync_event(input: *const u8, len: usize) -> *const u8 { pub extern "C" fn sync_event(_input: *const u8, _len: usize) -> *const u8 {
let request: AFPluginRequest = FFIRequest::from_u8_pointer(input, len).into(); error!("unimplemented sync_event");
#[cfg(feature = "sync_verbose_log")]
trace!("[FFI]: {} Sync Event: {:?}", &request.id, &request.event,);
let dispatcher = match APPFLOWY_CORE.dispatcher() {
None => {
error!("sdk not init yet.");
return forget_rust(Vec::default());
},
Some(dispatcher) => dispatcher,
};
let _response = AFPluginDispatcher::sync_send(dispatcher, request);
// FFIResponse { }
let response_bytes = vec![]; let response_bytes = vec![];
let result = extend_front_four_bytes_into_bytes(&response_bytes); let result = extend_front_four_bytes_into_bytes(&response_bytes);
forget_rust(result) forget_rust(result)
@ -161,7 +201,6 @@ pub extern "C" fn sync_event(input: *const u8, len: usize) -> *const u8 {
#[no_mangle] #[no_mangle]
pub extern "C" fn set_stream_port(notification_port: i64) -> i32 { pub extern "C" fn set_stream_port(notification_port: i64) -> i32 {
// Make sure hot reload won't register the notification sender twice
unregister_all_notification_sender(); unregister_all_notification_sender();
register_notification_sender(DartNotificationSender::new(notification_port)); register_notification_sender(DartNotificationSender::new(notification_port));
0 0
@ -169,8 +208,7 @@ pub extern "C" fn set_stream_port(notification_port: i64) -> i32 {
#[no_mangle] #[no_mangle]
pub extern "C" fn set_log_stream_port(port: i64) -> i32 { pub extern "C" fn set_log_stream_port(port: i64) -> i32 {
*LOG_STREAM_ISOLATE.lock().unwrap() = Some(Isolate::new(port)); *LOG_STREAM_ISOLATE.write().unwrap() = Some(Isolate::new(port));
0 0
} }
@ -181,31 +219,22 @@ pub extern "C" fn link_me_please() {}
#[inline(always)] #[inline(always)]
async fn post_to_flutter(response: AFPluginEventResponse, port: i64) { async fn post_to_flutter(response: AFPluginEventResponse, port: i64) {
let isolate = allo_isolate::Isolate::new(port); let isolate = allo_isolate::Isolate::new(port);
#[allow(clippy::blocks_in_conditions)] if let Ok(_) = isolate
match isolate
.catch_unwind(async { .catch_unwind(async {
let ffi_resp = FFIResponse::from(response); let ffi_resp = FFIResponse::from(response);
ffi_resp.into_bytes().unwrap().to_vec() ffi_resp.into_bytes().unwrap().to_vec()
}) })
.await .await
{ {
Ok(_success) => { #[cfg(feature = "sync_verbose_log")]
#[cfg(feature = "sync_verbose_log")] trace!("[FFI]: Post data to dart success");
trace!("[FFI]: Post data to dart success"); } else {
}, error!("[FFI]: allo_isolate post panic");
Err(e) => {
if let Some(msg) = e.downcast_ref::<&str>() {
error!("[FFI]: {:?}", msg);
} else {
error!("[FFI]: allo_isolate post panic");
}
},
} }
} }
#[no_mangle] #[no_mangle]
pub extern "C" fn rust_log(level: i64, data: *const c_char) { pub extern "C" fn rust_log(level: i64, data: *const c_char) {
// Check if the data pointer is not null
if data.is_null() { if data.is_null() {
error!("[flutter error]: null pointer provided to backend_log"); error!("[flutter error]: null pointer provided to backend_log");
return; return;
@ -213,7 +242,6 @@ pub extern "C" fn rust_log(level: i64, data: *const c_char) {
let log_result = unsafe { CStr::from_ptr(data) }.to_str(); let log_result = unsafe { CStr::from_ptr(data) }.to_str();
// Handle potential UTF-8 conversion error
let log_str = match log_result { let log_str = match log_result {
Ok(str) => str, Ok(str) => str,
Err(e) => { Err(e) => {
@ -225,29 +253,13 @@ pub extern "C" fn rust_log(level: i64, data: *const c_char) {
}, },
}; };
// Simplify logging by determining the log level outside of the match match level {
let log_level = match level { 0 => info!("[Flutter]: {}", log_str),
0 => "info", 1 => debug!("[Flutter]: {}", log_str),
1 => "debug", 2 => trace!("[Flutter]: {}", log_str),
2 => "trace", 3 => warn!("[Flutter]: {}", log_str),
3 => "warn", 4 => error!("[Flutter]: {}", log_str),
4 => "error", _ => warn!("[flutter error]: Unsupported log level: {}", level),
_ => {
warn!("[flutter error]: Unsupported log level: {}", level);
return;
},
};
// Log the message at the appropriate level
match log_level {
"info" => info!("[Flutter]: {}", log_str),
"debug" => debug!("[Flutter]: {}", log_str),
"trace" => trace!("[Flutter]: {}", log_str),
"warn" => warn!("[Flutter]: {}", log_str),
"error" => error!("[Flutter]: {}", log_str),
_ => {
warn!("[flutter error]: Unsupported log level: {}", log_level);
},
} }
} }

View File

@ -3,12 +3,13 @@ use flowy_user::errors::{internal_error, FlowyError};
use lib_dispatch::prelude::{ use lib_dispatch::prelude::{
AFPluginDispatcher, AFPluginEventResponse, AFPluginFromBytes, AFPluginRequest, ToBytes, *, AFPluginDispatcher, AFPluginEventResponse, AFPluginFromBytes, AFPluginRequest, ToBytes, *,
}; };
use std::rc::Rc; use std::sync::Arc;
use std::{ use std::{
convert::TryFrom, convert::TryFrom,
fmt::{Debug, Display}, fmt::{Debug, Display},
hash::Hash, hash::Hash,
}; };
use tokio::task::LocalSet;
#[derive(Clone)] #[derive(Clone)]
pub struct EventBuilder { pub struct EventBuilder {
@ -47,8 +48,9 @@ impl EventBuilder {
} }
pub async fn async_send(mut self) -> Self { pub async fn async_send(mut self) -> Self {
let local_set = LocalSet::new();
let request = self.get_request(); let request = self.get_request();
let resp = AFPluginDispatcher::async_send(self.dispatch().as_ref(), request).await; let resp = AFPluginDispatcher::async_send(self.dispatch().as_ref(), request, &local_set).await;
self.context.response = Some(resp); self.context.response = Some(resp);
self self
} }
@ -84,7 +86,7 @@ impl EventBuilder {
.map(|data| data.into_inner()) .map(|data| data.into_inner())
} }
fn dispatch(&self) -> Rc<AFPluginDispatcher> { fn dispatch(&self) -> Arc<AFPluginDispatcher> {
self.context.sdk.dispatcher() self.context.sdk.dispatcher()
} }

View File

@ -164,7 +164,7 @@ pub fn document_from_document_doc_state(doc_id: &str, doc_state: Vec<u8>) -> Doc
} }
async fn init_core(config: AppFlowyCoreConfig) -> AppFlowyCore { async fn init_core(config: AppFlowyCoreConfig) -> AppFlowyCore {
let runtime = Rc::new(AFPluginRuntime::new().unwrap()); let runtime = Arc::new(AFPluginRuntime::new().unwrap());
let cloned_runtime = runtime.clone(); let cloned_runtime = runtime.clone();
AppFlowyCore::new(config, cloned_runtime, None).await AppFlowyCore::new(config, cloned_runtime, None).await
} }

View File

@ -9,6 +9,7 @@ use flowy_folder::entities::{RepeatedViewPB, WorkspacePB};
use protobuf::ProtobufError; use protobuf::ProtobufError;
use tokio::sync::broadcast::{channel, Sender}; use tokio::sync::broadcast::{channel, Sender};
use tokio::task::LocalSet;
use tracing::error; use tracing::error;
use uuid::Uuid; use uuid::Uuid;
@ -73,11 +74,12 @@ impl EventIntegrationTest {
.unwrap(); .unwrap();
let request = AFPluginRequest::new(UserEvent::SignUp).payload(payload); let request = AFPluginRequest::new(UserEvent::SignUp).payload(payload);
let user_profile = AFPluginDispatcher::async_send(&self.appflowy_core.dispatcher(), request) let user_profile =
.await AFPluginDispatcher::async_send(&self.appflowy_core.dispatcher(), request, &LocalSet::new())
.parse::<UserProfilePB, FlowyError>() .await
.unwrap() .parse::<UserProfilePB, FlowyError>()
.unwrap(); .unwrap()
.unwrap();
// let _ = create_default_workspace_if_need(dispatch.clone(), &user_profile.id); // let _ = create_default_workspace_if_need(dispatch.clone(), &user_profile.id);
SignUpContext { SignUpContext {

View File

@ -2,7 +2,6 @@
use flowy_search::folder::indexer::FolderIndexManagerImpl; use flowy_search::folder::indexer::FolderIndexManagerImpl;
use flowy_search::services::manager::SearchManager; use flowy_search::services::manager::SearchManager;
use std::rc::Rc;
use std::sync::{Arc, Weak}; use std::sync::{Arc, Weak};
use std::time::Duration; use std::time::Duration;
use sysinfo::System; use sysinfo::System;
@ -55,7 +54,7 @@ pub struct AppFlowyCore {
pub document_manager: Arc<DocumentManager>, pub document_manager: Arc<DocumentManager>,
pub folder_manager: Arc<FolderManager>, pub folder_manager: Arc<FolderManager>,
pub database_manager: Arc<DatabaseManager>, pub database_manager: Arc<DatabaseManager>,
pub event_dispatcher: Rc<AFPluginDispatcher>, pub event_dispatcher: Arc<AFPluginDispatcher>,
pub server_provider: Arc<ServerProvider>, pub server_provider: Arc<ServerProvider>,
pub task_dispatcher: Arc<RwLock<TaskDispatcher>>, pub task_dispatcher: Arc<RwLock<TaskDispatcher>>,
pub store_preference: Arc<KVStorePreferences>, pub store_preference: Arc<KVStorePreferences>,
@ -67,7 +66,7 @@ pub struct AppFlowyCore {
impl AppFlowyCore { impl AppFlowyCore {
pub async fn new( pub async fn new(
config: AppFlowyCoreConfig, config: AppFlowyCoreConfig,
runtime: Rc<AFPluginRuntime>, runtime: Arc<AFPluginRuntime>,
stream_log_sender: Option<Arc<dyn StreamLogSender>>, stream_log_sender: Option<Arc<dyn StreamLogSender>>,
) -> Self { ) -> Self {
let platform = OperatingSystem::from(&config.platform); let platform = OperatingSystem::from(&config.platform);
@ -103,7 +102,7 @@ impl AppFlowyCore {
} }
#[instrument(skip(config, runtime))] #[instrument(skip(config, runtime))]
async fn init(config: AppFlowyCoreConfig, runtime: Rc<AFPluginRuntime>) -> Self { async fn init(config: AppFlowyCoreConfig, runtime: Arc<AFPluginRuntime>) -> Self {
// Init the key value database // Init the key value database
let store_preference = Arc::new(KVStorePreferences::new(&config.storage_path).unwrap()); let store_preference = Arc::new(KVStorePreferences::new(&config.storage_path).unwrap());
info!("🔥{:?}", &config); info!("🔥{:?}", &config);
@ -262,7 +261,7 @@ impl AppFlowyCore {
error!("Init user failed: {}", err) error!("Init user failed: {}", err)
} }
} }
let event_dispatcher = Rc::new(AFPluginDispatcher::new( let event_dispatcher = Arc::new(AFPluginDispatcher::new(
runtime, runtime,
make_plugins( make_plugins(
Arc::downgrade(&folder_manager), Arc::downgrade(&folder_manager),
@ -291,7 +290,7 @@ impl AppFlowyCore {
} }
/// Only expose the dispatcher in test /// Only expose the dispatcher in test
pub fn dispatcher(&self) -> Rc<AFPluginDispatcher> { pub fn dispatcher(&self) -> Arc<AFPluginDispatcher> {
self.event_dispatcher.clone() self.event_dispatcher.clone()
} }
} }

View File

@ -681,14 +681,16 @@ impl DatabaseEditor {
} }
pub async fn init_database_row(&self, row_id: &RowId) -> FlowyResult<()> { pub async fn init_database_row(&self, row_id: &RowId) -> FlowyResult<()> {
if self if let Some(database_row) = self.database.read().await.get_database_row(row_id) {
.database if !database_row
.read() .read()
.await .await
.get_database_row(row_id) .collab
.is_some() .get_state()
{ .is_uninitialized()
return Ok(()); {
return Ok(());
}
} }
debug!("Init database row: {}", row_id); debug!("Init database row: {}", row_id);
@ -696,7 +698,7 @@ impl DatabaseEditor {
.database .database
.read() .read()
.await .await
.create_database_row(row_id) .init_database_row(row_id)
.ok_or_else(|| { .ok_or_else(|| {
FlowyError::record_not_found() FlowyError::record_not_found()
.with_context(format!("The row:{} in database not found", row_id)) .with_context(format!("The row:{} in database not found", row_id))

View File

@ -157,9 +157,7 @@ impl FolderManager {
) -> Result<Arc<RwLock<Folder>>, FlowyError> { ) -> Result<Arc<RwLock<Folder>>, FlowyError> {
let folder_notifier = folder_notifier.into(); let folder_notifier = folder_notifier.into();
// only need the check the workspace id when the doc state is not from the disk. // only need the check the workspace id when the doc state is not from the disk.
let config = CollabBuilderConfig::default() let config = CollabBuilderConfig::default().sync_enable(true);
.sync_enable(true)
.auto_initialize(true);
let data_source = data_source let data_source = data_source
.unwrap_or_else(|| KVDBCollabPersistenceImpl::new(collab_db.clone(), uid).into_data_source()); .unwrap_or_else(|| KVDBCollabPersistenceImpl::new(collab_db.clone(), uid).into_data_source());

View File

@ -3,7 +3,7 @@ use pin_project::pin_project;
use std::any::Any; use std::any::Any;
use std::future::Future; use std::future::Future;
use std::pin::Pin; use std::pin::Pin;
use std::rc::Rc; use std::sync::Arc;
use std::task::{Context, Poll}; use std::task::{Context, Poll};
use tracing::event; use tracing::event;
@ -17,10 +17,10 @@ use crate::{
}; };
#[cfg(feature = "local_set")] #[cfg(feature = "local_set")]
pub trait AFConcurrent {} pub trait AFConcurrent: Send {}
#[cfg(feature = "local_set")] #[cfg(feature = "local_set")]
impl<T> AFConcurrent for T where T: ?Sized {} impl<T> AFConcurrent for T where T: Send + ?Sized {}
#[cfg(not(feature = "local_set"))] #[cfg(not(feature = "local_set"))]
pub trait AFConcurrent: Send + Sync {} pub trait AFConcurrent: Send + Sync {}
@ -47,7 +47,7 @@ pub(crate) fn downcast_owned<T: 'static + Send + Sync>(boxed: AFBox) -> Option<T
} }
#[cfg(feature = "local_set")] #[cfg(feature = "local_set")]
pub(crate) type AFBox = Box<dyn Any>; pub(crate) type AFBox = Box<dyn Any + Send + Sync>;
#[cfg(not(feature = "local_set"))] #[cfg(not(feature = "local_set"))]
pub(crate) type AFBox = Box<dyn Any + Send + Sync>; pub(crate) type AFBox = Box<dyn Any + Send + Sync>;
@ -70,11 +70,12 @@ where
pub struct AFPluginDispatcher { pub struct AFPluginDispatcher {
plugins: AFPluginMap, plugins: AFPluginMap,
runtime: Rc<AFPluginRuntime>, #[allow(dead_code)]
runtime: Arc<AFPluginRuntime>,
} }
impl AFPluginDispatcher { impl AFPluginDispatcher {
pub fn new(runtime: Rc<AFPluginRuntime>, plugins: Vec<AFPlugin>) -> AFPluginDispatcher { pub fn new(runtime: Arc<AFPluginRuntime>, plugins: Vec<AFPlugin>) -> AFPluginDispatcher {
tracing::trace!("{}", plugin_info(&plugins)); tracing::trace!("{}", plugin_info(&plugins));
AFPluginDispatcher { AFPluginDispatcher {
plugins: plugin_map_or_crash(plugins), plugins: plugin_map_or_crash(plugins),
@ -82,13 +83,111 @@ impl AFPluginDispatcher {
} }
} }
pub async fn async_send<Req>(dispatch: &AFPluginDispatcher, request: Req) -> AFPluginEventResponse #[cfg(feature = "local_set")]
pub async fn async_send<Req>(
dispatch: &AFPluginDispatcher,
request: Req,
local_set: &tokio::task::LocalSet,
) -> AFPluginEventResponse
where where
Req: Into<AFPluginRequest>, Req: Into<AFPluginRequest>,
{ {
AFPluginDispatcher::async_send_with_callback(dispatch, request, |_| Box::pin(async {})).await AFPluginDispatcher::async_send_with_callback(
dispatch,
request,
|_| Box::pin(async {}),
local_set,
)
.await
}
#[cfg(feature = "local_set")]
pub async fn async_send_with_callback<Req, Callback>(
dispatch: &AFPluginDispatcher,
request: Req,
callback: Callback,
local_set: &tokio::task::LocalSet,
) -> AFPluginEventResponse
where
Req: Into<AFPluginRequest>,
Callback: FnOnce(AFPluginEventResponse) -> AFBoxFuture<'static, ()> + AFConcurrent + 'static,
{
let request: AFPluginRequest = request.into();
let plugins = dispatch.plugins.clone();
let service = Box::new(DispatchService { plugins });
tracing::trace!("Async event: {:?}", &request.event);
let service_ctx = DispatchContext {
request,
callback: Some(Box::new(callback)),
};
let handle = local_set.spawn_local(async move {
service.call(service_ctx).await.unwrap_or_else(|e| {
tracing::error!("Dispatch runtime error: {:?}", e);
InternalError::Other(format!("{:?}", e)).as_response()
})
});
// let handle = tokio::spawn(async move {
// service.call(service_ctx).await.unwrap_or_else(|e| {
// tracing::error!("Dispatch runtime error: {:?}", e);
// InternalError::Other(format!("{:?}", e)).as_response()
// })
// });
let result: Result<AFPluginEventResponse, DispatchError> = local_set
.run_until(handle)
.await
.map_err(|e| e.to_string().into());
result.unwrap_or_else(|e| {
let msg = format!("EVENT_DISPATCH join error: {:?}", e);
tracing::error!("{}", msg);
let error = InternalError::JoinError(msg);
error.as_response()
})
} }
#[cfg(feature = "local_set")]
pub fn boxed_async_send_with_callback<Req, Callback>(
dispatch: &AFPluginDispatcher,
request: Req,
callback: Callback,
local_set: &tokio::task::LocalSet,
) -> DispatchFuture<AFPluginEventResponse>
where
Req: Into<AFPluginRequest> + 'static,
Callback: FnOnce(AFPluginEventResponse) -> AFBoxFuture<'static, ()> + AFConcurrent + 'static,
{
let request: AFPluginRequest = request.into();
let plugins = dispatch.plugins.clone();
let service = Box::new(DispatchService { plugins });
tracing::trace!("[dispatch]: Async event: {:?}", &request.event);
let service_ctx = DispatchContext {
request,
callback: Some(Box::new(callback)),
};
let handle = local_set.spawn_local(async move {
service.call(service_ctx).await.unwrap_or_else(|e| {
tracing::error!("Dispatch runtime error: {:?}", e);
InternalError::Other(format!("{:?}", e)).as_response()
})
});
let fut = local_set.run_until(handle);
let result = local_set.block_on(&dispatch.runtime.inner, fut);
DispatchFuture {
fut: Box::pin(async move {
result.unwrap_or_else(|e| {
let msg = format!("EVENT_DISPATCH join error: {:?}", e);
tracing::error!("{}", msg);
let error = InternalError::JoinError(msg);
error.as_response()
})
}),
}
}
#[cfg(not(feature = "local_set"))]
pub async fn async_send_with_callback<Req, Callback>( pub async fn async_send_with_callback<Req, Callback>(
dispatch: &AFPluginDispatcher, dispatch: &AFPluginDispatcher,
request: Req, request: Req,
@ -107,65 +206,25 @@ impl AFPluginDispatcher {
callback: Some(Box::new(callback)), callback: Some(Box::new(callback)),
}; };
// Spawns a future onto the runtime. dispatch
// .runtime
// This spawns the given future onto the runtime's executor, usually a .spawn(async move {
// thread pool. The thread pool is then responsible for polling the future
// until it completes.
//
// The provided future will start running in the background immediately
// when `spawn` is called, even if you don't await the returned
// `JoinHandle`.
let result: Result<AFPluginEventResponse, DispatchError>;
#[cfg(feature = "local_set")]
{
let handle = dispatch.runtime.local.spawn_local(async move {
service.call(service_ctx).await.unwrap_or_else(|e| { service.call(service_ctx).await.unwrap_or_else(|e| {
tracing::error!("Dispatch runtime error: {:?}", e); tracing::error!("Dispatch runtime error: {:?}", e);
InternalError::Other(format!("{:?}", e)).as_response() InternalError::Other(format!("{:?}", e)).as_response()
}) })
}); })
.await
result = dispatch .unwrap_or_else(|e| {
.runtime let msg = format!("EVENT_DISPATCH join error: {:?}", e);
.local tracing::error!("{}", msg);
.run_until(handle) let error = InternalError::JoinError(msg);
.await error.as_response()
.map_err(|e| e.to_string().into()) })
}
#[cfg(not(feature = "local_set"))]
{
result = dispatch
.runtime
.spawn(async move {
service.call(service_ctx).await.unwrap_or_else(|e| {
tracing::error!("Dispatch runtime error: {:?}", e);
InternalError::Other(format!("{:?}", e)).as_response()
})
})
.await;
}
result.unwrap_or_else(|e| {
let msg = format!("EVENT_DISPATCH join error: {:?}", e);
tracing::error!("{}", msg);
let error = InternalError::JoinError(msg);
error.as_response()
})
} }
pub fn box_async_send<Req>( #[cfg(not(feature = "local_set"))]
dispatch: &AFPluginDispatcher, pub async fn boxed_async_send_with_callback<Req, Callback>(
request: Req,
) -> DispatchFuture<AFPluginEventResponse>
where
Req: Into<AFPluginRequest> + 'static,
{
AFPluginDispatcher::boxed_async_send_with_callback(dispatch, request, |_| Box::pin(async {}))
}
pub fn boxed_async_send_with_callback<Req, Callback>(
dispatch: &AFPluginDispatcher, dispatch: &AFPluginDispatcher,
request: Req, request: Req,
callback: Callback, callback: Callback,
@ -183,76 +242,39 @@ impl AFPluginDispatcher {
callback: Some(Box::new(callback)), callback: Some(Box::new(callback)),
}; };
#[cfg(feature = "local_set")] let handle = dispatch.runtime.spawn(async move {
{ service.call(service_ctx).await.unwrap_or_else(|e| {
let handle = dispatch.runtime.local.spawn_local(async move { tracing::error!("[dispatch]: runtime error: {:?}", e);
service.call(service_ctx).await.unwrap_or_else(|e| { InternalError::Other(format!("{:?}", e)).as_response()
tracing::error!("Dispatch runtime error: {:?}", e); })
InternalError::Other(format!("{:?}", e)).as_response() });
let runtime = dispatch.runtime.clone();
DispatchFuture {
fut: Box::pin(async move {
let result = runtime.spawn(handle).await.unwrap();
result.unwrap_or_else(|e| {
let msg = format!("EVENT_DISPATCH join error: {:?}", e);
tracing::error!("{}", msg);
let error = InternalError::JoinError(msg);
error.as_response()
}) })
}); }),
let fut = dispatch.runtime.local.run_until(handle);
let result = dispatch.runtime.block_on(fut);
DispatchFuture {
fut: Box::pin(async move {
result.unwrap_or_else(|e| {
let msg = format!("EVENT_DISPATCH join error: {:?}", e);
tracing::error!("{}", msg);
let error = InternalError::JoinError(msg);
error.as_response()
})
}),
}
}
#[cfg(not(feature = "local_set"))]
{
let handle = dispatch.runtime.spawn(async move {
service
.call(crate::service::service::Service)
.await
.unwrap_or_else(|e| {
tracing::error!("[dispatch]: runtime error: {:?}", e);
InternalError::Other(format!("{:?}", e)).as_response()
})
});
let runtime = dispatch.runtime.clone();
DispatchFuture {
fut: Box::pin(async move {
let result = runtime.run_until(handle).await;
result.unwrap_or_else(|e| {
let msg = format!("EVENT_DISPATCH join error: {:?}", e);
tracing::error!("{}", msg);
let error = InternalError::JoinError(msg);
error.as_response()
})
}),
}
} }
} }
#[cfg(not(target_arch = "wasm32"))] #[cfg(feature = "local_set")]
pub fn sync_send( pub fn sync_send(
dispatch: Rc<AFPluginDispatcher>, dispatch: Arc<AFPluginDispatcher>,
request: AFPluginRequest, request: AFPluginRequest,
) -> AFPluginEventResponse { ) -> AFPluginEventResponse {
futures::executor::block_on(AFPluginDispatcher::async_send_with_callback( futures::executor::block_on(AFPluginDispatcher::async_send_with_callback(
dispatch.as_ref(), dispatch.as_ref(),
request, request,
|_| Box::pin(async {}), |_| Box::pin(async {}),
&tokio::task::LocalSet::new(),
)) ))
} }
#[track_caller]
pub fn spawn<F>(&self, future: F) -> tokio::task::JoinHandle<F::Output>
where
F: Future + Send + 'static,
<F as Future>::Output: Send + 'static,
{
self.runtime.spawn(future)
}
} }
#[derive(Derivative)] #[derive(Derivative)]

View File

@ -13,7 +13,7 @@ impl AFPluginStateMap {
pub fn insert<T>(&mut self, val: T) -> Option<T> pub fn insert<T>(&mut self, val: T) -> Option<T>
where where
T: 'static + AFConcurrent, T: 'static + Send + Sync,
{ {
self self
.0 .0

View File

@ -53,7 +53,7 @@ where
impl<T> FromAFPluginRequest for AFPluginState<T> impl<T> FromAFPluginRequest for AFPluginState<T>
where where
T: ?Sized + AFConcurrent + 'static, T: ?Sized + Send + Sync + 'static,
{ {
type Error = DispatchError; type Error = DispatchError;
type Future = Ready<Result<Self, DispatchError>>; type Future = Ready<Result<Self, DispatchError>>;

View File

@ -13,7 +13,6 @@ use crate::{
use futures_core::ready; use futures_core::ready;
use nanoid::nanoid; use nanoid::nanoid;
use pin_project::pin_project; use pin_project::pin_project;
use std::rc::Rc;
use std::sync::Arc; use std::sync::Arc;
use std::{ use std::{
collections::HashMap, collections::HashMap,
@ -25,12 +24,12 @@ use std::{
task::{Context, Poll}, task::{Context, Poll},
}; };
pub type AFPluginMap = Rc<HashMap<AFPluginEvent, Rc<AFPlugin>>>; pub type AFPluginMap = Arc<HashMap<AFPluginEvent, Arc<AFPlugin>>>;
pub(crate) fn plugin_map_or_crash(plugins: Vec<AFPlugin>) -> AFPluginMap { pub(crate) fn plugin_map_or_crash(plugins: Vec<AFPlugin>) -> AFPluginMap {
let mut plugin_map: HashMap<AFPluginEvent, Rc<AFPlugin>> = HashMap::new(); let mut plugin_map: HashMap<AFPluginEvent, Arc<AFPlugin>> = HashMap::new();
plugins.into_iter().for_each(|m| { plugins.into_iter().for_each(|m| {
let events = m.events(); let events = m.events();
let plugins = Rc::new(m); let plugins = Arc::new(m);
events.into_iter().for_each(|e| { events.into_iter().for_each(|e| {
if plugin_map.contains_key(&e) { if plugin_map.contains_key(&e) {
let plugin_name = plugin_map.get(&e).map(|p| &p.name); let plugin_name = plugin_map.get(&e).map(|p| &p.name);
@ -39,7 +38,7 @@ pub(crate) fn plugin_map_or_crash(plugins: Vec<AFPlugin>) -> AFPluginMap {
plugin_map.insert(e, plugins.clone()); plugin_map.insert(e, plugins.clone());
}); });
}); });
Rc::new(plugin_map) Arc::new(plugin_map)
} }
#[derive(PartialEq, Eq, Hash, Debug, Clone)] #[derive(PartialEq, Eq, Hash, Debug, Clone)]
@ -66,7 +65,7 @@ pub struct AFPlugin {
/// Contains a list of factories that are used to generate the services used to handle the passed-in /// Contains a list of factories that are used to generate the services used to handle the passed-in
/// `ServiceRequest`. /// `ServiceRequest`.
/// ///
event_service_factory: Rc< event_service_factory: Arc<
HashMap<AFPluginEvent, BoxServiceFactory<(), ServiceRequest, ServiceResponse, DispatchError>>, HashMap<AFPluginEvent, BoxServiceFactory<(), ServiceRequest, ServiceResponse, DispatchError>>,
>, >,
} }
@ -76,7 +75,7 @@ impl std::default::Default for AFPlugin {
Self { Self {
name: "".to_owned(), name: "".to_owned(),
states: Default::default(), states: Default::default(),
event_service_factory: Rc::new(HashMap::new()), event_service_factory: Arc::new(HashMap::new()),
} }
} }
} }
@ -91,7 +90,7 @@ impl AFPlugin {
self self
} }
pub fn state<D: AFConcurrent + 'static>(mut self, data: D) -> Self { pub fn state<D: Send + Sync + 'static>(mut self, data: D) -> Self {
Arc::get_mut(&mut self.states) Arc::get_mut(&mut self.states)
.unwrap() .unwrap()
.insert(crate::module::AFPluginState::new(data)); .insert(crate::module::AFPluginState::new(data));
@ -112,7 +111,7 @@ impl AFPlugin {
if self.event_service_factory.contains_key(&event) { if self.event_service_factory.contains_key(&event) {
panic!("Register duplicate Event: {:?}", &event); panic!("Register duplicate Event: {:?}", &event);
} else { } else {
Rc::get_mut(&mut self.event_service_factory) Arc::get_mut(&mut self.event_service_factory)
.unwrap() .unwrap()
.insert(event, factory(AFPluginHandlerService::new(handler))); .insert(event, factory(AFPluginHandlerService::new(handler)));
} }
@ -184,7 +183,7 @@ impl AFPluginServiceFactory<AFPluginRequest> for AFPlugin {
} }
pub struct AFPluginService { pub struct AFPluginService {
services: Rc< services: Arc<
HashMap<AFPluginEvent, BoxServiceFactory<(), ServiceRequest, ServiceResponse, DispatchError>>, HashMap<AFPluginEvent, BoxServiceFactory<(), ServiceRequest, ServiceResponse, DispatchError>>,
>, >,
states: AFStateMap, states: AFStateMap,

View File

@ -8,7 +8,7 @@ use std::{
use derivative::*; use derivative::*;
use futures_core::ready; use futures_core::ready;
use crate::prelude::{AFConcurrent, AFStateMap}; use crate::prelude::AFStateMap;
use crate::{ use crate::{
errors::{DispatchError, InternalError}, errors::{DispatchError, InternalError},
module::AFPluginEvent, module::AFPluginEvent,
@ -39,7 +39,7 @@ impl AFPluginEventRequest {
pub fn get_state<T>(&self) -> Option<T> pub fn get_state<T>(&self) -> Option<T>
where where
T: AFConcurrent + 'static + Clone, T: Send + Sync + 'static + Clone,
{ {
if let Some(data) = self.states.get::<T>() { if let Some(data) = self.states.get::<T>() {
return Some(data.clone()); return Some(data.clone());

View File

@ -7,17 +7,15 @@ use tokio::runtime::Runtime;
use tokio::task::JoinHandle; use tokio::task::JoinHandle;
pub struct AFPluginRuntime { pub struct AFPluginRuntime {
inner: Runtime, pub(crate) inner: Runtime,
#[cfg(feature = "local_set")]
pub(crate) local: tokio::task::LocalSet,
} }
impl Display for AFPluginRuntime { impl Display for AFPluginRuntime {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
if cfg!(any(target_arch = "wasm32", feature = "local_set")) { if cfg!(any(target_arch = "wasm32", feature = "local_set")) {
write!(f, "Runtime(current_thread)") write!(f, "Runtime(local_set)")
} else { } else {
write!(f, "Runtime(multi_thread)") write!(f, "Runtime")
} }
} }
} }
@ -25,11 +23,7 @@ impl Display for AFPluginRuntime {
impl AFPluginRuntime { impl AFPluginRuntime {
pub fn new() -> io::Result<Self> { pub fn new() -> io::Result<Self> {
let inner = default_tokio_runtime()?; let inner = default_tokio_runtime()?;
Ok(Self { Ok(Self { inner })
inner,
#[cfg(feature = "local_set")]
local: tokio::task::LocalSet::new(),
})
} }
#[track_caller] #[track_caller]
@ -41,16 +35,6 @@ impl AFPluginRuntime {
self.inner.spawn(future) self.inner.spawn(future)
} }
#[cfg(feature = "local_set")]
#[track_caller]
pub fn block_on<F>(&self, f: F) -> F::Output
where
F: Future,
{
self.local.block_on(&self.inner, f)
}
#[cfg(not(feature = "local_set"))]
#[track_caller] #[track_caller]
pub fn block_on<F>(&self, f: F) -> F::Output pub fn block_on<F>(&self, f: F) -> F::Output
where where
@ -62,21 +46,11 @@ impl AFPluginRuntime {
#[cfg(feature = "local_set")] #[cfg(feature = "local_set")]
pub fn default_tokio_runtime() -> io::Result<Runtime> { pub fn default_tokio_runtime() -> io::Result<Runtime> {
#[cfg(not(target_arch = "wasm32"))] runtime::Builder::new_multi_thread()
{ .enable_io()
runtime::Builder::new_multi_thread() .enable_time()
.enable_io() .thread_name("dispatch-rt-st")
.enable_time() .build()
.thread_name("dispatch-rt-st")
.build()
}
#[cfg(target_arch = "wasm32")]
{
runtime::Builder::new_current_thread()
.thread_name("dispatch-rt-st")
.build()
}
} }
#[cfg(not(feature = "local_set"))] #[cfg(not(feature = "local_set"))]

View File

@ -1,7 +1,7 @@
use std::rc::Rc;
use lib_dispatch::prelude::*; use lib_dispatch::prelude::*;
use lib_dispatch::runtime::AFPluginRuntime; use lib_dispatch::runtime::AFPluginRuntime;
use std::sync::Arc;
use tokio::task::LocalSet;
pub async fn hello() -> String { pub async fn hello() -> String {
"say hello".to_string() "say hello".to_string()
@ -10,17 +10,22 @@ pub async fn hello() -> String {
#[tokio::test] #[tokio::test]
async fn test() { async fn test() {
let event = "1"; let event = "1";
let runtime = Rc::new(AFPluginRuntime::new().unwrap()); let runtime = Arc::new(AFPluginRuntime::new().unwrap());
let dispatch = Rc::new(AFPluginDispatcher::new( let dispatch = Arc::new(AFPluginDispatcher::new(
runtime, runtime,
vec![AFPlugin::new().event(event, hello)], vec![AFPlugin::new().event(event, hello)],
)); ));
let request = AFPluginRequest::new(event); let request = AFPluginRequest::new(event);
let _ = AFPluginDispatcher::async_send_with_callback(dispatch.as_ref(), request, |resp| { let _ = AFPluginDispatcher::async_send_with_callback(
Box::pin(async move { dispatch.as_ref(),
dbg!(&resp); request,
}) |resp| {
}) Box::pin(async move {
dbg!(&resp);
})
},
&LocalSet::new(),
)
.await; .await;
std::mem::forget(dispatch); std::mem::forget(dispatch);