mirror of
https://github.com/infinilabs/coco-app.git
synced 2025-12-16 19:47:43 +01:00
refactor: remove thread app list synchronizer as it leaks memory on macOS (#573)
This commit is contained in:
@@ -12,7 +12,7 @@ use crate::util::open;
|
|||||||
use crate::GLOBAL_TAURI_APP_HANDLE;
|
use crate::GLOBAL_TAURI_APP_HANDLE;
|
||||||
use applications::{App, AppTrait};
|
use applications::{App, AppTrait};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use log::{debug, error, info, warn};
|
use log::{error, warn};
|
||||||
use pizza_engine::document::FieldType;
|
use pizza_engine::document::FieldType;
|
||||||
use pizza_engine::document::{
|
use pizza_engine::document::{
|
||||||
Document as PizzaEngineDocument, DraftDoc as PizzaEngineDraftDoc, FieldValue,
|
Document as PizzaEngineDocument, DraftDoc as PizzaEngineDraftDoc, FieldValue,
|
||||||
@@ -24,8 +24,6 @@ use pizza_engine::store::{DiskStore, DiskStoreSnapshot};
|
|||||||
use pizza_engine::writer::Writer;
|
use pizza_engine::writer::Writer;
|
||||||
use pizza_engine::{doc, Engine, EngineBuilder};
|
use pizza_engine::{doc, Engine, EngineBuilder};
|
||||||
use serde_json::Value as Json;
|
use serde_json::Value as Json;
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::collections::HashSet;
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use tauri::{async_runtime, AppHandle, Manager, Runtime};
|
use tauri::{async_runtime, AppHandle, Manager, Runtime};
|
||||||
use tauri_plugin_fs_pro::{icon, metadata, name, IconOptions};
|
use tauri_plugin_fs_pro::{icon, metadata, name, IconOptions};
|
||||||
@@ -48,7 +46,6 @@ const TAURI_STORE_APP_ALIAS: &str = "app_alias";
|
|||||||
const TAURI_STORE_KEY_SEARCH_PATH: &str = "search_path";
|
const TAURI_STORE_KEY_SEARCH_PATH: &str = "search_path";
|
||||||
const TAURI_STORE_KEY_DISABLED_APP_LIST: &str = "disabled_app_list";
|
const TAURI_STORE_KEY_DISABLED_APP_LIST: &str = "disabled_app_list";
|
||||||
|
|
||||||
const THREAD_NAME_APP_SYNCHRONIZER: &str = "local app search - app list synchronizer";
|
|
||||||
|
|
||||||
/// We use this as:
|
/// We use this as:
|
||||||
///
|
///
|
||||||
@@ -196,6 +193,9 @@ macro_rules! task_exec_try {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fields `engine` and `writer` become unused without app list synchronizer, allow
|
||||||
|
// this rather than removing these fields as we will bring the synchronizer back.
|
||||||
|
#[allow(dead_code)]
|
||||||
struct ApplicationSearchSourceState {
|
struct ApplicationSearchSourceState {
|
||||||
engine: Engine<DiskStore>,
|
engine: Engine<DiskStore>,
|
||||||
writer: Writer<DiskStore>,
|
writer: Writer<DiskStore>,
|
||||||
@@ -373,6 +373,10 @@ impl<R: Runtime> Task for SearchApplicationsTask<R> {
|
|||||||
/// 2. New search paths have been added by the user
|
/// 2. New search paths have been added by the user
|
||||||
///
|
///
|
||||||
/// We use this task to index them.
|
/// We use this task to index them.
|
||||||
|
//
|
||||||
|
// This become unused without app list synchronizer, allow this rather than
|
||||||
|
// removing the task as we will bring the synchronizer back.
|
||||||
|
#[allow(dead_code)]
|
||||||
struct IndexNewApplicationsTask {
|
struct IndexNewApplicationsTask {
|
||||||
applications: Vec<PizzaEngineDraftDoc>,
|
applications: Vec<PizzaEngineDraftDoc>,
|
||||||
callback: Option<tokio::sync::oneshot::Sender<Result<(), String>>>,
|
callback: Option<tokio::sync::oneshot::Sender<Result<(), String>>>,
|
||||||
@@ -459,123 +463,6 @@ impl ApplicationSearchSource {
|
|||||||
|
|
||||||
register_app_hotkey_upon_start(app_handle.clone())?;
|
register_app_hotkey_upon_start(app_handle.clone())?;
|
||||||
|
|
||||||
if indexing_applications_result.is_err() {
|
|
||||||
warn!(
|
|
||||||
"thread [{}] won't start because indexing applications failed",
|
|
||||||
THREAD_NAME_APP_SYNCHRONIZER
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
let app_handle_clone = app_handle.clone();
|
|
||||||
std::thread::Builder::new()
|
|
||||||
.name(THREAD_NAME_APP_SYNCHRONIZER.into())
|
|
||||||
.spawn(move || {
|
|
||||||
let tokio_rt = tokio::runtime::Builder::new_current_thread()
|
|
||||||
.enable_all()
|
|
||||||
.build()
|
|
||||||
.expect("failed to start a tokio runtime");
|
|
||||||
|
|
||||||
tokio_rt.block_on(async move {
|
|
||||||
info!("thread [{}] started", THREAD_NAME_APP_SYNCHRONIZER);
|
|
||||||
loop {
|
|
||||||
tokio::time::sleep(std::time::Duration::from_secs(60 * 2)).await;
|
|
||||||
debug!("app list synchronizer working");
|
|
||||||
|
|
||||||
let stored_app_list = get_app_list(app_handle_clone.clone())
|
|
||||||
.await
|
|
||||||
.expect("failed to fetch the stored app list");
|
|
||||||
let store = app_handle_clone
|
|
||||||
.store(TAURI_STORE_DISABLED_APP_LIST_AND_SEARCH_PATH)
|
|
||||||
.unwrap_or_else(|_e| {
|
|
||||||
panic!(
|
|
||||||
"store [{}] not found/loaded",
|
|
||||||
TAURI_STORE_DISABLED_APP_LIST_AND_SEARCH_PATH
|
|
||||||
)
|
|
||||||
});
|
|
||||||
let search_path_json =
|
|
||||||
store.get(TAURI_STORE_KEY_SEARCH_PATH).unwrap_or_else(|| {
|
|
||||||
panic!("key [{}] not found", TAURI_STORE_KEY_SEARCH_PATH)
|
|
||||||
});
|
|
||||||
let search_paths: Vec<String> = match search_path_json {
|
|
||||||
Json::Array(array) => array
|
|
||||||
.into_iter()
|
|
||||||
.map(|json| match json {
|
|
||||||
Json::String(str) => str,
|
|
||||||
_ => unreachable!("search path should be a string"),
|
|
||||||
})
|
|
||||||
.collect(),
|
|
||||||
_ => unreachable!("search paths should be stored in an array"),
|
|
||||||
};
|
|
||||||
let mut current_app_list =
|
|
||||||
list_app_in(search_paths).unwrap_or_else(|e| {
|
|
||||||
panic!("failed to fetch app list due to error [{}]", e)
|
|
||||||
});
|
|
||||||
// filter out Coco-AI
|
|
||||||
current_app_list
|
|
||||||
.retain(|app| app.name != app_handle.package_info().name);
|
|
||||||
|
|
||||||
let current_app_list_path_hash_index = {
|
|
||||||
let mut index = HashMap::new();
|
|
||||||
for (idx, app) in current_app_list.iter().enumerate() {
|
|
||||||
index.insert(get_app_path(app), idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
index
|
|
||||||
};
|
|
||||||
let current_app_path_list: HashSet<String> =
|
|
||||||
current_app_list.iter().map(get_app_path).collect();
|
|
||||||
let stored_app_path_list: HashSet<String> = stored_app_list
|
|
||||||
.iter()
|
|
||||||
.map(|app_entry| app_entry.path.clone())
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let new_apps = current_app_path_list.difference(&stored_app_path_list);
|
|
||||||
debug!("found new apps [{:?}]", new_apps);
|
|
||||||
|
|
||||||
// Synchronize the stored app list
|
|
||||||
let mut new_apps_pizza_engine_documents = Vec::new();
|
|
||||||
|
|
||||||
for new_app_path in new_apps {
|
|
||||||
let idx =
|
|
||||||
*current_app_list_path_hash_index.get(new_app_path).unwrap();
|
|
||||||
let new_app = current_app_list.get(idx).unwrap();
|
|
||||||
let new_app_name = get_app_name(new_app).await;
|
|
||||||
let new_app_icon_path =
|
|
||||||
get_app_icon_path(&app_handle_clone, new_app).await.unwrap();
|
|
||||||
let new_app_alias = get_app_alias(&app_handle_clone, &new_app_path)
|
|
||||||
.unwrap_or(String::new());
|
|
||||||
|
|
||||||
let new_app_pizza_engine_document = doc!(new_app_path.clone(), {
|
|
||||||
FIELD_APP_NAME => new_app_name,
|
|
||||||
FIELD_ICON_PATH => new_app_icon_path,
|
|
||||||
FIELD_APP_ALIAS => new_app_alias,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
new_apps_pizza_engine_documents.push(new_app_pizza_engine_document);
|
|
||||||
}
|
|
||||||
|
|
||||||
let (callback, wait_for_complete) = tokio::sync::oneshot::channel();
|
|
||||||
let index_new_apps_task = Box::new(IndexNewApplicationsTask {
|
|
||||||
applications: new_apps_pizza_engine_documents,
|
|
||||||
callback: Some(callback),
|
|
||||||
});
|
|
||||||
RUNTIME_TX
|
|
||||||
.get()
|
|
||||||
.unwrap()
|
|
||||||
.send(index_new_apps_task)
|
|
||||||
.expect("rx dropped, pizza runtime could possibly be dead");
|
|
||||||
wait_for_complete
|
|
||||||
.await
|
|
||||||
.expect("tx dropped, pizza runtime could possibly be dead")
|
|
||||||
.unwrap_or_else(|e| {
|
|
||||||
panic!("failed to index new apps due to error [{}]", e)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user