use crate::lua::lua_script_callback_engine::LuaScriptCallbackEngine;
use crate::types::event_callback::{EventCallback, EventData};
use anyhow::Result;
use async_trait::async_trait;
use tracing::warn;
pub struct LuaEventCallback {
lua: LuaScriptCallbackEngine,
}
impl LuaEventCallback {
#[allow(clippy::new_without_default)]
pub fn new(
memory_limit: usize,
allow_lua_os_library: bool,
unsafe_lua: bool,
callback_timeout_milliseconds: u64,
) -> Self {
let lua = if unsafe_lua {
LuaScriptCallbackEngine::unsafe_new(memory_limit, callback_timeout_milliseconds)
} else if allow_lua_os_library {
LuaScriptCallbackEngine::new(memory_limit, callback_timeout_milliseconds)
} else {
LuaScriptCallbackEngine::new_without_os_io_libs(
memory_limit,
callback_timeout_milliseconds,
)
};
Self { lua }
}
pub fn load_and_compile(&mut self, script_path: &str) -> Result<()> {
let lua_script = std::fs::read(script_path)?;
self.lua.load_and_compile(&String::from_utf8(lua_script)?)
}
}
#[async_trait]
impl EventCallback for LuaEventCallback {
async fn on_event(&mut self, event_data: EventData) {
let event_data_lua = self.lua.get_engine().create_table().unwrap();
event_data_lua
.set("event_type", event_data.event_type.bits())
.unwrap();
event_data_lua.set("dry_run", event_data.dry_run).unwrap();
event_data_lua.set("key", event_data.key.clone()).unwrap();
event_data_lua
.set("source_version_id", event_data.source_version_id.clone())
.unwrap();
event_data_lua
.set("target_version_id", event_data.target_version_id.clone())
.unwrap();
event_data_lua
.set(
"source_last_modified",
event_data.source_last_modified.map(|dt| dt.to_string()),
)
.unwrap();
event_data_lua
.set(
"target_last_modified",
event_data.target_last_modified.map(|dt| dt.to_string()),
)
.unwrap();
event_data_lua
.set("source_size", event_data.source_size)
.unwrap();
event_data_lua
.set("target_size", event_data.target_size)
.unwrap();
event_data_lua
.set(
"checksum_algorithm",
event_data.checksum_algorithm.map(|alg| alg.to_string()),
)
.unwrap();
event_data_lua
.set("source_checksum", event_data.source_checksum.clone())
.unwrap();
event_data_lua
.set("target_checksum", event_data.target_checksum.clone())
.unwrap();
event_data_lua
.set("source_etag", event_data.source_etag.clone())
.unwrap();
event_data_lua
.set("target_etag", event_data.target_etag.clone())
.unwrap();
event_data_lua
.set(
"source_content_type",
event_data.source_content_type.clone(),
)
.unwrap();
event_data_lua
.set(
"source_user_defined_metadata",
event_data.source_user_defined_metadata.clone(),
)
.unwrap();
event_data_lua
.set("source_tagging", event_data.source_tagging.clone())
.unwrap();
event_data_lua
.set("byte_written", event_data.byte_written)
.unwrap();
event_data_lua
.set("upload_id", event_data.upload_id.clone())
.unwrap();
event_data_lua
.set("part_number", event_data.part_number)
.unwrap();
event_data_lua
.set("message", event_data.message.clone())
.unwrap();
event_data_lua
.set("stats_transferred_byte", event_data.stats_transferred_byte)
.unwrap();
event_data_lua
.set(
"stats_transferred_byte_per_sec",
event_data.stats_transferred_byte_per_sec,
)
.unwrap();
event_data_lua
.set(
"stats_transferred_object",
event_data.stats_transferred_object,
)
.unwrap();
event_data_lua
.set(
"stats_transferred_object_per_sec",
event_data.stats_transferred_object_per_sec,
)
.unwrap();
event_data_lua
.set("stats_etag_verified", event_data.stats_etag_verified)
.unwrap();
event_data_lua
.set("stats_etag_mismatch", event_data.stats_etag_mismatch)
.unwrap();
event_data_lua
.set(
"stats_checksum_verified",
event_data.stats_checksum_verified,
)
.unwrap();
event_data_lua
.set(
"stats_checksum_mismatch",
event_data.stats_checksum_mismatch,
)
.unwrap();
event_data_lua
.set("stats_deleted", event_data.stats_deleted)
.unwrap();
event_data_lua
.set("stats_skipped", event_data.stats_skipped)
.unwrap();
event_data_lua
.set("stats_error", event_data.stats_error)
.unwrap();
event_data_lua
.set("stats_warning", event_data.stats_warning)
.unwrap();
event_data_lua
.set("stats_duration_sec", event_data.stats_duration_sec)
.unwrap();
self.lua.reset_deadline();
let func: mlua::Result<mlua::Function> = self.lua.get_engine().globals().get("on_event");
if let Err(e) = func {
warn!("Lua function 'on_event' not found: {}", e);
return;
}
let func_result: mlua::Result<()> = func.unwrap().call_async(event_data_lua).await;
if let Err(e) = func_result {
warn!("Error executing Lua event callback: {}", e);
return;
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn create_callback() {
let _callback = LuaEventCallback::new(8 * 1024 * 1024, false, false, 0);
let _callback = LuaEventCallback::new(8 * 1024 * 1024, true, false, 0);
let _callback = LuaEventCallback::new(0, true, true, 0);
}
}