Delete src/plugins/bad-worker.rs
This commit is contained in:
parent
709e35f929
commit
8ecb76101b
@ -1,309 +0,0 @@
|
|||||||
//! Worker поток для обработки сообщений плагинов
|
|
||||||
|
|
||||||
use std::sync::Arc;
|
|
||||||
use std::thread;
|
|
||||||
use std::time::Duration;
|
|
||||||
use parking_lot::RwLock;
|
|
||||||
use crossbeam::channel::{Sender, TryRecvError};
|
|
||||||
use serde_json::Value;
|
|
||||||
|
|
||||||
use crate::plugins::channel::{
|
|
||||||
PluginMessage, PluginChannels, HookResponse, LoadPluginResponse,
|
|
||||||
UnloadPluginResponse, ListPluginsResponse, GetPluginResponse, PluginInfo
|
|
||||||
};
|
|
||||||
use crate::plugins::traits::{PluginEvent, PluginHook, PluginState};
|
|
||||||
use crate::plugins::sandbox::LuaSandbox;
|
|
||||||
use super::Plugin;
|
|
||||||
|
|
||||||
/// Worker для обработки плагинов
|
|
||||||
pub struct PluginWorker {
|
|
||||||
channels: PluginChannels,
|
|
||||||
plugins: Arc<RwLock<Vec<Arc<Plugin>>>>,
|
|
||||||
handle: Option<thread::JoinHandle<()>>,
|
|
||||||
shutdown_flag: Arc<RwLock<bool>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PluginWorker {
|
|
||||||
/// Создать новый worker
|
|
||||||
pub fn new(channels: PluginChannels, plugins: Arc<RwLock<Vec<Arc<Plugin>>>>) -> Self {
|
|
||||||
Self {
|
|
||||||
channels,
|
|
||||||
plugins,
|
|
||||||
handle: None,
|
|
||||||
shutdown_flag: Arc::new(RwLock::new(false)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Запустить worker
|
|
||||||
pub fn start(&mut self) {
|
|
||||||
let channels = self.channels.clone();
|
|
||||||
let plugins = Arc::clone(&self.plugins);
|
|
||||||
let shutdown_flag = Arc::clone(&self.shutdown_flag);
|
|
||||||
|
|
||||||
let handle = thread::spawn(move || {
|
|
||||||
PluginWorker::run_loop(channels, plugins, shutdown_flag);
|
|
||||||
});
|
|
||||||
|
|
||||||
self.handle = Some(handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Основной цикл обработки сообщений
|
|
||||||
fn run_loop(
|
|
||||||
channels: PluginChannels,
|
|
||||||
plugins: Arc<RwLock<Vec<Arc<Plugin>>>>,
|
|
||||||
shutdown_flag: Arc<RwLock<bool>>,
|
|
||||||
) {
|
|
||||||
while !*shutdown_flag.read() {
|
|
||||||
match channels.try_recv() {
|
|
||||||
Ok(message) => {
|
|
||||||
PluginWorker::process_message(message, &channels, &plugins);
|
|
||||||
}
|
|
||||||
Err(TryRecvError::Empty) => {
|
|
||||||
// Нет сообщений, ждем немного
|
|
||||||
thread::sleep(Duration::from_millis(10));
|
|
||||||
}
|
|
||||||
Err(TryRecvError::Disconnected) => {
|
|
||||||
// Канал закрыт, выходим
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
log::info!("Plugin worker stopped");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Обработать сообщение
|
|
||||||
fn process_message(
|
|
||||||
message: PluginMessage,
|
|
||||||
channels: &PluginChannels,
|
|
||||||
plugins: &Arc<RwLock<Vec<Arc<Plugin>>>>,
|
|
||||||
) {
|
|
||||||
match message {
|
|
||||||
PluginMessage::Event(event) => {
|
|
||||||
PluginWorker::handle_event(event, plugins);
|
|
||||||
}
|
|
||||||
|
|
||||||
PluginMessage::HookRequest { hook_name, data, response_sender } => {
|
|
||||||
let response = PluginWorker::execute_hook_internal(&hook_name, data, plugins);
|
|
||||||
let _ = response_sender.send(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
PluginMessage::LoadPlugin { path, response_sender } => {
|
|
||||||
let response = PluginWorker::load_plugin_internal(&path, plugins);
|
|
||||||
let _ = response_sender.send(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
PluginMessage::UnloadPlugin { plugin_id, response_sender } => {
|
|
||||||
let response = PluginWorker::unload_plugin_internal(&plugin_id, plugins);
|
|
||||||
let _ = response_sender.send(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
PluginMessage::ListPlugins { response_sender } => {
|
|
||||||
let response = PluginWorker::list_plugins_internal(plugins);
|
|
||||||
let _ = response_sender.send(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
PluginMessage::GetPlugin { plugin_id, response_sender } => {
|
|
||||||
let response = PluginWorker::get_plugin_internal(&plugin_id, plugins);
|
|
||||||
let _ = response_sender.send(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
PluginMessage::Shutdown => {
|
|
||||||
log::info!("Shutdown signal received");
|
|
||||||
// Флаг будет установлен в основном цикле
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Обработать событие
|
|
||||||
fn handle_event(event: PluginEvent, plugins: &Arc<RwLock<Vec<Arc<Plugin>>>>) {
|
|
||||||
let plugins_guard = plugins.read();
|
|
||||||
|
|
||||||
for plugin in plugins_guard.iter() {
|
|
||||||
if let Some(sandbox) = &plugin.lua_sandbox {
|
|
||||||
let sandbox_guard = sandbox.read();
|
|
||||||
if let Err(e) = sandbox_guard.handle_event(&event) {
|
|
||||||
log::error!("Failed to handle event in plugin {}: {}", plugin.id, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Выполнить хук (внутренняя реализация)
|
|
||||||
fn execute_hook_internal(
|
|
||||||
hook_name: &str,
|
|
||||||
data: Value,
|
|
||||||
plugins: &Arc<RwLock<Vec<Arc<Plugin>>>>,
|
|
||||||
) -> HookResponse {
|
|
||||||
let plugins_guard = plugins.read();
|
|
||||||
|
|
||||||
// Сначала собираем все хуки с указанным именем
|
|
||||||
let mut hooks = Vec::new();
|
|
||||||
|
|
||||||
for plugin in plugins_guard.iter() {
|
|
||||||
for hook in &plugin.hooks {
|
|
||||||
if hook.name == hook_name {
|
|
||||||
hooks.push((plugin, hook));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Сортируем по приоритету (высокий приоритет = больше значение)
|
|
||||||
hooks.sort_by(|a, b| b.1.priority.cmp(&a.1.priority));
|
|
||||||
|
|
||||||
// Выполняем хуки по порядку
|
|
||||||
let mut last_result = data;
|
|
||||||
|
|
||||||
for (plugin, hook) in hooks {
|
|
||||||
if let Some(sandbox) = &plugin.lua_sandbox {
|
|
||||||
let sandbox_guard = sandbox.read();
|
|
||||||
match sandbox_guard.execute_hook(&hook.function, last_result.clone()) {
|
|
||||||
Ok(result) => {
|
|
||||||
last_result = result;
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
return HookResponse::Error(format!("Failed to execute hook {} in plugin {}: {}",
|
|
||||||
hook_name, plugin.id, e));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HookResponse::Success(last_result)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Загрузить плагин (внутренняя реализация)
|
|
||||||
fn load_plugin_internal(
|
|
||||||
path: &str,
|
|
||||||
plugins: &Arc<RwLock<Vec<Arc<Plugin>>>>,
|
|
||||||
) -> LoadPluginResponse {
|
|
||||||
use std::fs;
|
|
||||||
|
|
||||||
// Проверяем, не загружен ли уже плагин с таким путем
|
|
||||||
{
|
|
||||||
let plugins_guard = plugins.read();
|
|
||||||
if plugins_guard.iter().any(|p| p.path == path) {
|
|
||||||
return LoadPluginResponse::Error(format!("Plugin already loaded: {}", path));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Читаем файл плагина
|
|
||||||
let content = match fs::read_to_string(path) {
|
|
||||||
Ok(content) => content,
|
|
||||||
Err(e) => return LoadPluginResponse::Error(format!("Failed to read plugin file: {}", e)),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Создаем песочницу Lua
|
|
||||||
let sandbox = match LuaSandbox::new() {
|
|
||||||
Ok(sandbox) => sandbox,
|
|
||||||
Err(e) => return LoadPluginResponse::Error(format!("Failed to create Lua sandbox: {}", e)),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Загружаем плагин в песочницу
|
|
||||||
let plugin_info = match sandbox.load_plugin(&content, path) {
|
|
||||||
Ok(info) => info,
|
|
||||||
Err(e) => return LoadPluginResponse::Error(format!("Failed to load plugin: {}", e)),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Создаем объект плагина
|
|
||||||
let plugin = Arc::new(Plugin {
|
|
||||||
id: plugin_info.id.clone(),
|
|
||||||
name: plugin_info.name.clone(),
|
|
||||||
version: plugin_info.version.clone(),
|
|
||||||
description: plugin_info.description.clone(),
|
|
||||||
author: plugin_info.author.clone(),
|
|
||||||
path: path.to_string(),
|
|
||||||
state: PluginState::Loaded,
|
|
||||||
hooks: plugin_info.hooks.clone(),
|
|
||||||
lua_sandbox: Some(Arc::new(RwLock::new(sandbox))),
|
|
||||||
});
|
|
||||||
|
|
||||||
// Добавляем плагин в список
|
|
||||||
{
|
|
||||||
let mut plugins_guard = plugins.write();
|
|
||||||
plugins_guard.push(plugin);
|
|
||||||
}
|
|
||||||
|
|
||||||
log::info!("Plugin loaded: {} v{}", plugin_info.name, plugin_info.version);
|
|
||||||
LoadPluginResponse::Success(plugin_info.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Выгрузить плагин (внутренняя реализация)
|
|
||||||
fn unload_plugin_internal(
|
|
||||||
plugin_id: &str,
|
|
||||||
plugins: &Arc<RwLock<Vec<Arc<Plugin>>>>,
|
|
||||||
) -> UnloadPluginResponse {
|
|
||||||
let mut plugins_guard = plugins.write();
|
|
||||||
|
|
||||||
if let Some(pos) = plugins_guard.iter().position(|p| p.id == plugin_id) {
|
|
||||||
let plugin = plugins_guard.remove(pos);
|
|
||||||
log::info!("Plugin unloaded: {} v{}", plugin.name, plugin.version);
|
|
||||||
UnloadPluginResponse::Success
|
|
||||||
} else {
|
|
||||||
UnloadPluginResponse::Error(format!("Plugin not found: {}", plugin_id))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Получить список плагинов (внутренняя реализация)
|
|
||||||
fn list_plugins_internal(
|
|
||||||
plugins: &Arc<RwLock<Vec<Arc<Plugin>>>>,
|
|
||||||
) -> ListPluginsResponse {
|
|
||||||
let plugins_guard = plugins.read();
|
|
||||||
|
|
||||||
let plugin_infos = plugins_guard.iter().map(|plugin| {
|
|
||||||
PluginInfo {
|
|
||||||
id: plugin.id.clone(),
|
|
||||||
name: plugin.name.clone(),
|
|
||||||
version: plugin.version.clone(),
|
|
||||||
description: plugin.description.clone(),
|
|
||||||
author: plugin.author.clone(),
|
|
||||||
path: plugin.path.clone(),
|
|
||||||
state: format!("{:?}", plugin.state),
|
|
||||||
hooks: plugin.hooks.clone(),
|
|
||||||
}
|
|
||||||
}).collect();
|
|
||||||
|
|
||||||
ListPluginsResponse {
|
|
||||||
plugins: plugin_infos,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Получить информацию о плагине (внутренняя реализация)
|
|
||||||
fn get_plugin_internal(
|
|
||||||
plugin_id: &str,
|
|
||||||
plugins: &Arc<RwLock<Vec<Arc<Plugin>>>>,
|
|
||||||
) -> GetPluginResponse {
|
|
||||||
let plugins_guard = plugins.read();
|
|
||||||
|
|
||||||
if let Some(plugin) = plugins_guard.iter().find(|p| p.id == plugin_id) {
|
|
||||||
let info = PluginInfo {
|
|
||||||
id: plugin.id.clone(),
|
|
||||||
name: plugin.name.clone(),
|
|
||||||
version: plugin.version.clone(),
|
|
||||||
description: plugin.description.clone(),
|
|
||||||
author: plugin.author.clone(),
|
|
||||||
path: plugin.path.clone(),
|
|
||||||
state: format!("{:?}", plugin.state),
|
|
||||||
hooks: plugin.hooks.clone(),
|
|
||||||
};
|
|
||||||
GetPluginResponse::Found(info)
|
|
||||||
} else {
|
|
||||||
GetPluginResponse::NotFound
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Остановить worker
|
|
||||||
pub fn shutdown(&self) {
|
|
||||||
*self.shutdown_flag.write() = true;
|
|
||||||
|
|
||||||
if let Some(handle) = self.handle.take() {
|
|
||||||
let _ = handle.join();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Drop for PluginWorker {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
self.shutdown();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
x
Reference in New Issue
Block a user