Delete src/plugins/bad-mod.rs

This commit is contained in:
Григорий Сафронов 2026-01-18 21:54:58 +00:00
parent de119b9b15
commit c5ec1d432b

View File

@ -1,340 +0,0 @@
//! Система плагинов для flusql с lock-free архитектурой
//!
//! Основные возможности:
//! - Lock-free обработка событий через каналы
//! - Песочница для плагинов Lua
//! - Поддержка хуков и событий
//! - Горячая перезагрузка плагинов
//! - Безопасная обработка ошибок
//! - Асинхронное выполнение задач
mod traits;
mod channel;
mod sandbox;
mod worker;
pub use traits::{
PluginData, PluginState, EventHandler, HookHandler,
PluginEvent, EventType, PluginHook, PluginManagerTrait
};
pub use channel::{
PluginMessage, PluginChannels, HookResponse, LoadPluginResponse,
UnloadPluginResponse, ListPluginsResponse, GetPluginResponse, PluginInfo
};
pub use sandbox::LuaSandbox;
pub use worker::PluginWorker;
use std::sync::Arc;
use parking_lot::RwLock;
use mlua::Lua;
use serde_json::Value;
/// Ошибки плагинов
#[derive(Debug, thiserror::Error)]
pub enum PluginError {
#[error("IO error: {0}")]
IoError(#[from] std::io::Error),
#[error("Lua error: {0}")]
LuaError(String),
#[error("Serialization error: {0}")]
SerializationError(#[from] serde_json::Error),
#[error("Channel error: {0}")]
ChannelError(String),
#[error("Plugin not found: {0}")]
PluginNotFound(String),
#[error("Plugin already loaded: {0}")]
PluginAlreadyLoaded(String),
#[error("Invalid plugin: {0}")]
InvalidPlugin(String),
}
/// Реализация данных плагина
pub struct Plugin {
pub id: String,
pub name: String,
pub version: String,
pub description: String,
pub author: String,
pub path: String,
pub state: PluginState,
pub hooks: Vec<PluginHook>,
pub lua_sandbox: Option<Arc<RwLock<LuaSandbox>>>,
}
impl PluginData for Plugin {
fn id(&self) -> &str {
&self.id
}
fn name(&self) -> &str {
&self.name
}
fn version(&self) -> &str {
&self.version
}
fn description(&self) -> &str {
&self.description
}
fn author(&self) -> &str {
&self.author
}
fn path(&self) -> &str {
&self.path
}
fn state(&self) -> PluginState {
self.state
}
}
/// Менеджер плагинов с lock-free архитектурой
pub struct PluginManager {
plugins: Arc<RwLock<Vec<Arc<Plugin>>>>,
channels: PluginChannels,
worker: PluginWorker,
}
impl PluginManager {
/// Создать новый менеджер плагинов
pub fn new() -> Self {
let channels = PluginChannels::new();
let plugins = Arc::new(RwLock::new(Vec::new()));
let worker = PluginWorker::new(
channels.clone(),
Arc::clone(&plugins),
);
// Запустить worker в фоновом потоке
worker.start();
Self {
plugins,
channels,
worker,
}
}
/// Отправить событие (lock-free, через канал)
pub async fn emit_event(&self, event: PluginEvent) -> Result<(), PluginError> {
self.channels.send(PluginMessage::Event(event))
.map_err(|e| PluginError::ChannelError(e))
}
/// Выполнить хук (lock-free, через канал)
pub async fn execute_hook(&self, hook_name: &str, data: Value) -> Result<Value, PluginError> {
let (sender, receiver) = crossbeam::channel::bounded(1);
self.channels.send(PluginMessage::HookRequest {
hook_name: hook_name.to_string(),
data,
response_sender: sender,
}).map_err(|e| PluginError::ChannelError(e))?;
match receiver.recv() {
Ok(HookResponse::Success(result)) => Ok(result),
Ok(HookResponse::Error(err)) => Err(PluginError::LuaError(err)),
Ok(HookResponse::NoHandler) => Err(PluginError::InvalidPlugin("No handler found".to_string())),
Err(e) => Err(PluginError::ChannelError(format!("Failed to receive hook response: {}", e))),
}
}
/// Загрузить плагин (lock-free, через канал)
pub async fn load_plugin(&self, path: &str) -> Result<String, PluginError> {
let (sender, receiver) = crossbeam::channel::bounded(1);
self.channels.send(PluginMessage::LoadPlugin {
path: path.to_string(),
response_sender: sender,
}).map_err(|e| PluginError::ChannelError(e))?;
match receiver.recv() {
Ok(LoadPluginResponse::Success(plugin_id)) => Ok(plugin_id),
Ok(LoadPluginResponse::Error(err)) => Err(PluginError::InvalidPlugin(err)),
Err(e) => Err(PluginError::ChannelError(format!("Failed to receive load response: {}", e))),
}
}
/// Выгрузить плагин (lock-free, через канал)
pub async fn unload_plugin(&self, plugin_id: &str) -> Result<(), PluginError> {
let (sender, receiver) = crossbeam::channel::bounded(1);
self.channels.send(PluginMessage::UnloadPlugin {
plugin_id: plugin_id.to_string(),
response_sender: sender,
}).map_err(|e| PluginError::ChannelError(e))?;
match receiver.recv() {
Ok(UnloadPluginResponse::Success) => Ok(()),
Ok(UnloadPluginResponse::Error(err)) => Err(PluginError::InvalidPlugin(err)),
Err(e) => Err(PluginError::ChannelError(format!("Failed to receive unload response: {}", e))),
}
}
/// Получить список плагинов (lock-free, через канал)
pub async fn list_plugins(&self) -> Result<Vec<PluginInfo>, PluginError> {
let (sender, receiver) = crossbeam::channel::bounded(1);
self.channels.send(PluginMessage::ListPlugins {
response_sender: sender,
}).map_err(|e| PluginError::ChannelError(e))?;
match receiver.recv() {
Ok(response) => Ok(response.plugins),
Err(e) => Err(PluginError::ChannelError(format!("Failed to receive list response: {}", e))),
}
}
/// Получить информацию о плагине (lock-free, через канал)
pub async fn get_plugin(&self, plugin_id: &str) -> Result<Option<PluginInfo>, PluginError> {
let (sender, receiver) = crossbeam::channel::bounded(1);
self.channels.send(PluginMessage::GetPlugin {
plugin_id: plugin_id.to_string(),
response_sender: sender,
}).map_err(|e| PluginError::ChannelError(e))?;
match receiver.recv() {
Ok(GetPluginResponse::Found(info)) => Ok(Some(info)),
Ok(GetPluginResponse::NotFound) => Ok(None),
Ok(GetPluginResponse::Error(err)) => Err(PluginError::InvalidPlugin(err)),
Err(e) => Err(PluginError::ChannelError(format!("Failed to receive get response: {}", e))),
}
}
/// Загрузить все плагины из директории
pub async fn load_all_plugins(&self) -> Result<Vec<String>, PluginError> {
use std::fs;
use std::path::Path;
let plugins_dir = Path::new("./plugins");
if !plugins_dir.exists() {
fs::create_dir_all(plugins_dir)
.map_err(PluginError::IoError)?;
return Ok(Vec::new());
}
let mut loaded = Vec::new();
for entry in fs::read_dir(plugins_dir)
.map_err(PluginError::IoError)?
{
let entry = entry.map_err(PluginError::IoError)?;
let path = entry.path();
if path.is_file() && path.extension().and_then(|s| s.to_str()) == Some("lua") {
if let Ok(plugin_id) = self.load_plugin(path.to_str().unwrap()).await {
loaded.push(plugin_id);
}
}
}
Ok(loaded)
}
/// Остановить менеджер плагинов
pub fn shutdown(&self) {
self.channels.send(PluginMessage::Shutdown)
.unwrap_or_else(|e| log::error!("Failed to send shutdown message: {}", e));
// Дожидаемся остановки worker
self.worker.shutdown();
}
}
impl PluginManagerTrait for PluginManager {
fn load_all_plugins(&mut self) -> Result<Vec<Arc<dyn PluginData>>, String> {
// Для синхронного вызова используем tokio runtime
let rt = tokio::runtime::Runtime::new()
.map_err(|e| format!("Failed to create runtime: {}", e))?;
rt.block_on(async {
self.load_all_plugins().await
.map_err(|e| e.to_string())?;
let plugins = self.plugins.read();
let result: Vec<Arc<dyn PluginData>> = plugins
.iter()
.map(|p| p.clone() as Arc<dyn PluginData>)
.collect();
Ok(result)
})
}
fn load_plugin(&mut self, path: &str) -> Result<Arc<dyn PluginData>, String> {
let rt = tokio::runtime::Runtime::new()
.map_err(|e| format!("Failed to create runtime: {}", e))?;
rt.block_on(async {
let plugin_id = self.load_plugin(path).await
.map_err(|e| e.to_string())?;
let plugins = self.plugins.read();
plugins.iter()
.find(|p| p.id == plugin_id)
.map(|p| p.clone() as Arc<dyn PluginData>)
.ok_or_else(|| format!("Plugin not found after loading: {}", plugin_id))
})
}
fn unload_plugin(&mut self, plugin_id: &str) -> Result<(), String> {
let rt = tokio::runtime::Runtime::new()
.map_err(|e| format!("Failed to create runtime: {}", e))?;
rt.block_on(async {
self.unload_plugin(plugin_id).await
.map_err(|e| e.to_string())
})
}
fn list_plugins(&self) -> Vec<Arc<dyn PluginData>> {
let plugins = self.plugins.read();
plugins.iter()
.map(|p| p.clone() as Arc<dyn PluginData>)
.collect()
}
fn get_plugin(&self, plugin_id: &str) -> Option<Arc<dyn PluginData>> {
let plugins = self.plugins.read();
plugins.iter()
.find(|p| p.id == plugin_id)
.map(|p| p.clone() as Arc<dyn PluginData>)
}
fn emit_event(&self, event: PluginEvent) -> Result<(), String> {
let rt = tokio::runtime::Runtime::new()
.map_err(|e| format!("Failed to create runtime: {}", e))?;
rt.block_on(async {
self.emit_event(event).await
.map_err(|e| e.to_string())
})
}
fn execute_hook(&self, hook_name: &str, data: Value) -> Result<Value, String> {
let rt = tokio::runtime::Runtime::new()
.map_err(|e| format!("Failed to create runtime: {}", e))?;
rt.block_on(async {
self.execute_hook(hook_name, data).await
.map_err(|e| e.to_string())
})
}
}
impl Drop for PluginManager {
fn drop(&mut self) {
self.shutdown();
}
}