mirror of
https://github.com/infinilabs/coco-app.git
synced 2025-12-16 11:37:47 +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 applications::{App, AppTrait};
|
||||
use async_trait::async_trait;
|
||||
use log::{debug, error, info, warn};
|
||||
use log::{error, warn};
|
||||
use pizza_engine::document::FieldType;
|
||||
use pizza_engine::document::{
|
||||
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::{doc, Engine, EngineBuilder};
|
||||
use serde_json::Value as Json;
|
||||
use std::collections::HashMap;
|
||||
use std::collections::HashSet;
|
||||
use std::path::PathBuf;
|
||||
use tauri::{async_runtime, AppHandle, Manager, Runtime};
|
||||
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_DISABLED_APP_LIST: &str = "disabled_app_list";
|
||||
|
||||
const THREAD_NAME_APP_SYNCHRONIZER: &str = "local app search - app list synchronizer";
|
||||
|
||||
/// 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 {
|
||||
engine: Engine<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
|
||||
///
|
||||
/// 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 {
|
||||
applications: Vec<PizzaEngineDraftDoc>,
|
||||
callback: Option<tokio::sync::oneshot::Sender<Result<(), String>>>,
|
||||
@@ -459,123 +463,6 @@ impl ApplicationSearchSource {
|
||||
|
||||
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(())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user