143 lines
4.9 KiB
Rust
Executable File
143 lines
4.9 KiB
Rust
Executable File
// src/server/lua_engine.rs
|
|
//! Встроенный интерпретатор Lua (на основе rlua)
|
|
|
|
use rlua::{Lua, RluaCompat};
|
|
use std::sync::Arc;
|
|
use std::fs;
|
|
use std::path::Path;
|
|
|
|
use crate::common::Result;
|
|
use crate::common::protocol;
|
|
use crate::server::database::{Trigger, TriggerEvent, Index, IndexType};
|
|
|
|
/// Движок Lua для выполнения скриптов
|
|
#[derive(Clone)]
|
|
pub struct LuaEngine {
|
|
lua: Arc<Lua>,
|
|
}
|
|
|
|
impl LuaEngine {
|
|
pub fn new() -> Result<Self> {
|
|
let lua = Lua::new();
|
|
|
|
// Настройка Lua окружения
|
|
lua.load(r#"
|
|
function futriix_log(message)
|
|
print("LUA: " .. message)
|
|
end
|
|
|
|
function futriix_error(message)
|
|
print("LUA ERROR: " .. message)
|
|
end
|
|
"#).exec()?;
|
|
|
|
Ok(Self { lua: Arc::new(lua) })
|
|
}
|
|
|
|
/// Выполнение Lua скрипта из файла
|
|
#[allow(dead_code)]
|
|
pub fn execute_script_file(&self, file_path: &str) -> Result<()> {
|
|
let script_content = fs::read_to_string(file_path)
|
|
.map_err(|e| crate::common::FutriixError::LuaError(format!("Failed to read script file {}: {}", file_path, e)))?;
|
|
|
|
self.execute_script(&script_content)
|
|
}
|
|
|
|
/// Выполнение Lua скрипта из строки
|
|
pub fn execute_script(&self, script: &str) -> Result<()> {
|
|
let lua = self.lua.clone();
|
|
lua.load(script).exec()?;
|
|
Ok(())
|
|
}
|
|
|
|
/// Выполнение всех скриптов из директории
|
|
#[allow(dead_code)]
|
|
pub fn execute_scripts_from_dir(&self, dir_path: &str, script_names: &[String]) -> Result<()> {
|
|
let path = Path::new(dir_path);
|
|
|
|
if !path.exists() {
|
|
println!("Lua scripts directory does not exist: {}", path.display());
|
|
return Ok(());
|
|
}
|
|
|
|
if !path.is_dir() {
|
|
return Err(crate::common::FutriixError::LuaError(
|
|
format!("Lua scripts path is not a directory: {}", path.display())
|
|
));
|
|
}
|
|
|
|
for script_name in script_names {
|
|
let script_path = path.join(script_name);
|
|
|
|
if script_path.exists() && script_path.is_file() {
|
|
println!("Executing Lua script: {}", script_path.display());
|
|
|
|
match self.execute_script_file(script_path.to_str().unwrap()) {
|
|
Ok(_) => println!("✓ Script executed successfully: {}", script_name),
|
|
Err(e) => eprintln!("✗ Failed to execute script {}: {}", script_name, e),
|
|
}
|
|
} else {
|
|
println!("Script not found: {}", script_path.display());
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Регистрация функций базы данных в Lua
|
|
pub fn register_db_functions(
|
|
&self,
|
|
db: Arc<crate::server::database::Database>,
|
|
sharding_manager: Arc<crate::server::sharding::ShardingManager>
|
|
) -> Result<()> {
|
|
let lua = self.lua.clone();
|
|
|
|
// Создаем таблицу для функций БД
|
|
let futriix_db = lua.create_table()?;
|
|
|
|
// Базовые CRUD функции
|
|
let db_clone = db.clone();
|
|
futriix_db.set("create", lua.create_function(move |_, (collection, data): (String, String)| {
|
|
let command = protocol::Command::Create {
|
|
collection,
|
|
document: data.into_bytes(),
|
|
};
|
|
match db_clone.execute_command(command) {
|
|
Ok(_) => Ok(()),
|
|
Err(e) => Err(rlua::Error::RuntimeError(e.to_string())),
|
|
}
|
|
})?)?;
|
|
|
|
let db_clone = db.clone();
|
|
futriix_db.set("read", lua.create_function(move |_, (collection, id): (String, String)| {
|
|
let command = protocol::Command::Read {
|
|
collection,
|
|
id,
|
|
};
|
|
match db_clone.execute_command(command) {
|
|
Ok(response) => {
|
|
match response {
|
|
protocol::Response::Success(data) => {
|
|
Ok(String::from_utf8_lossy(&data).to_string())
|
|
}
|
|
protocol::Response::Error(e) => {
|
|
Err(rlua::Error::RuntimeError(e))
|
|
}
|
|
}
|
|
}
|
|
Err(e) => Err(rlua::Error::RuntimeError(e.to_string())),
|
|
}
|
|
})?)?;
|
|
|
|
// Добавляем таблицу в глобальное пространство имен
|
|
lua.globals().set("futriix_db", futriix_db)?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Получение директории Lua скриптов
|
|
fn lua_scripts_dir(&self) -> &'static str {
|
|
"lua_scripts"
|
|
}
|
|
}
|