fix: DriveCompiler compilation errors
Some checks failed
BotServer CI/CD / build (push) Failing after 1s
Some checks failed
BotServer CI/CD / build (push) Failing after 1s
- Fix Diesel query to use correct column types - Remove non-existent drive::configure() call - Clean up unused imports
This commit is contained in:
parent
1218d1b968
commit
fd786cd7da
2 changed files with 46 additions and 46 deletions
|
|
@ -1,19 +1,19 @@
|
||||||
/// DriveCompiler - Compilador unificado para GBDialog
|
/// DriveCompiler - Compilador unificado para GBDialog
|
||||||
///
|
///
|
||||||
/// Fluxo CORRETO:
|
/// Fluxo CORRETO:
|
||||||
/// 1. DriveMonitor (S3) lê MinIO diretamente
|
/// 1. DriveMonitor (S3) lê MinIO diretamente
|
||||||
/// 2. Baixa .bas para /opt/gbo/work/{bot}.gbai/{bot}.gbdialog/
|
/// 2. Baixa .bas para /opt/gbo/work/{bot}.gbai/{bot}.gbdialog/
|
||||||
/// 3. Compila .bas → .ast (no mesmo work dir)
|
/// 3. Compila .bas → .ast (no mesmo work dir)
|
||||||
/// 4. drive_files table controla etag/status
|
/// 4. drive_files table controla etag/status
|
||||||
///
|
///
|
||||||
/// SEM usar /opt/gbo/data/ como intermediário!
|
/// SEM usar /opt/gbo/data/ como intermediário!
|
||||||
|
|
||||||
use crate::basic::compiler::BasicCompiler;
|
use crate::basic::compiler::BasicCompiler;
|
||||||
use crate::core::shared::state::AppState;
|
use crate::core::shared::state::AppState;
|
||||||
use crate::core::shared::utils::get_work_path;
|
use crate::core::shared::utils::get_work_path;
|
||||||
use crate::drive::drive_files::{drive_files as drive_files_table, DriveFileRepository};
|
use crate::drive::drive_files::drive_files as drive_files_table;
|
||||||
use diesel::prelude::*;
|
use diesel::prelude::*;
|
||||||
use log::{debug, error, info, warn};
|
use log::{debug, error, info};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
@ -33,7 +33,7 @@ pub struct DriveCompiler {
|
||||||
impl DriveCompiler {
|
impl DriveCompiler {
|
||||||
pub fn new(state: Arc<AppState>) -> Self {
|
pub fn new(state: Arc<AppState>) -> Self {
|
||||||
let work_root = PathBuf::from(get_work_path());
|
let work_root = PathBuf::from(get_work_path());
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
state,
|
state,
|
||||||
work_root,
|
work_root,
|
||||||
|
|
@ -45,68 +45,68 @@ impl DriveCompiler {
|
||||||
/// Iniciar loop de compilação baseado em drive_files
|
/// Iniciar loop de compilação baseado em drive_files
|
||||||
pub async fn start_compiling(&self) -> Result<(), Box<dyn Error + Send + Sync>> {
|
pub async fn start_compiling(&self) -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
info!("DriveCompiler started - compiling .bas files directly to work dir");
|
info!("DriveCompiler started - compiling .bas files directly to work dir");
|
||||||
|
|
||||||
self.is_processing.store(true, Ordering::SeqCst);
|
self.is_processing.store(true, Ordering::SeqCst);
|
||||||
|
|
||||||
let compiler = self.clone();
|
let compiler = self.clone();
|
||||||
|
|
||||||
// Loop que verifica drive_files a cada 30s
|
// Loop que verifica drive_files a cada 30s
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
let mut interval = tokio::time::interval(Duration::from_secs(30));
|
let mut interval = tokio::time::interval(Duration::from_secs(30));
|
||||||
|
|
||||||
while compiler.is_processing.load(Ordering::SeqCst) {
|
while compiler.is_processing.load(Ordering::SeqCst) {
|
||||||
interval.tick().await;
|
interval.tick().await;
|
||||||
|
|
||||||
if let Err(e) = compiler.check_and_compile().await {
|
if let Err(e) = compiler.check_and_compile().await {
|
||||||
error!("DriveCompiler error: {}", e);
|
error!("DriveCompiler error: {}", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Verifica drive_files e compila arquivos .bas que mudaram
|
/// Verifica drive_files e compila arquivos .bas que mudaram
|
||||||
async fn check_and_compile(&self) -> Result<(), Box<dyn Error + Send + Sync>> {
|
async fn check_and_compile(&self) -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
use drive_files_table::dsl::*;
|
use drive_files_table::dsl::*;
|
||||||
|
|
||||||
let mut conn = self.state.conn.get()?;
|
let mut conn = self.state.conn.get()?;
|
||||||
|
|
||||||
// Selecionar todos os arquivos .gbdialog/*.bas
|
// Selecionar todos os arquivos .gbdialog/*.bas
|
||||||
let files: Vec<(Uuid, String, String, Option<String>)> = drive_files_table
|
let files: Vec<(Uuid, String, String, Option<String>)> = drive_files_table
|
||||||
.filter(file_type.eq("bas"))
|
.filter(file_type.eq("bas"))
|
||||||
.filter(file_path.like("%.gbdialog/%"))
|
.filter(file_path.like("%.gbdialog/%"))
|
||||||
.select((bot_id, file_path, file_type, etag.clone()))
|
.select((bot_id, file_path, file_type, etag))
|
||||||
.load(&mut conn)?;
|
.load(&mut conn)?;
|
||||||
|
|
||||||
for (bot_id, file_path, _file_type, current_etag_opt) in files {
|
for (bot_id, file_path_str, _file_type, current_etag_opt) in files {
|
||||||
let current_etag = current_etag_opt.unwrap_or_default();
|
let current_etag = current_etag_opt.unwrap_or_default();
|
||||||
|
|
||||||
// Verificar se precisa compilar
|
// Verificar se precisa compilar
|
||||||
let should_compile = {
|
let should_compile = {
|
||||||
let etags = self.last_etags.read().await;
|
let etags = self.last_etags.read().await;
|
||||||
etags.get(&file_path).map(|e| e != ¤t_etag).unwrap_or(true)
|
etags.get(&file_path_str).map(|e| e != ¤t_etag).unwrap_or(true)
|
||||||
};
|
};
|
||||||
|
|
||||||
if should_compile {
|
if should_compile {
|
||||||
debug!("DriveCompiler: {} changed, compiling...", file_path);
|
debug!("DriveCompiler: {} changed, compiling...", file_path_str);
|
||||||
|
|
||||||
// Compilar diretamente para work dir
|
// Compilar diretamente para work dir
|
||||||
if let Err(e) = self.compile_file(bot_id, &file_path).await {
|
if let Err(e) = self.compile_file(bot_id, &file_path_str).await {
|
||||||
error!("Failed to compile {}: {}", file_path, e);
|
error!("Failed to compile {}: {}", file_path_str, e);
|
||||||
} else {
|
} else {
|
||||||
// Atualizar estado
|
// Atualizar estado
|
||||||
let mut etags = self.last_etags.write().await;
|
let mut etags = self.last_etags.write().await;
|
||||||
etags.insert(file_path.clone(), current_etag.clone());
|
etags.insert(file_path_str.clone(), current_etag.clone());
|
||||||
|
|
||||||
info!("DriveCompiler: {} compiled successfully", file_path);
|
info!("DriveCompiler: {} compiled successfully", file_path_str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compilar arquivo .bas → .ast DIRETAMENTE em work/{bot}.gbai/{bot}.gbdialog/
|
/// Compilar arquivo .bas → .ast DIRETAMENTE em work/{bot}.gbai/{bot}.gbdialog/
|
||||||
async fn compile_file(&self, bot_id: Uuid, file_path: &str) -> Result<(), Box<dyn Error + Send + Sync>> {
|
async fn compile_file(&self, bot_id: Uuid, file_path: &str) -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
// file_path: {bot}.gbai/{bot}.gbdialog/{tool}.bas
|
// file_path: {bot}.gbai/{bot}.gbdialog/{tool}.bas
|
||||||
|
|
@ -114,39 +114,39 @@ impl DriveCompiler {
|
||||||
if parts.len() < 3 {
|
if parts.len() < 3 {
|
||||||
return Err("Invalid file path format".into());
|
return Err("Invalid file path format".into());
|
||||||
}
|
}
|
||||||
|
|
||||||
let bot_name = parts[0].trim_end_matches(".gbai");
|
let bot_name = parts[0].trim_end_matches(".gbai");
|
||||||
let tool_name = parts.last().unwrap().trim_end_matches(".bas");
|
let tool_name = parts.last().unwrap().trim_end_matches(".bas");
|
||||||
|
|
||||||
// Work dir: /opt/gbo/work/{bot}.gbai/{bot}.gbdialog/
|
// Work dir: /opt/gbo/work/{bot}.gbai/{bot}.gbdialog/
|
||||||
let work_dir = self.work_root.join(format!("{}.gbai/{}.gbdialog", bot_name, bot_name));
|
let work_dir = self.work_root.join(format!("{}.gbai/{}.gbdialog", bot_name, bot_name));
|
||||||
std::fs::create_dir_all(&work_dir)?;
|
std::fs::create_dir_all(&work_dir)?;
|
||||||
|
|
||||||
// Caminho do .bas no work
|
// Caminho do .bas no work
|
||||||
let work_bas_path = work_dir.join(format!("{}.bas", tool_name));
|
let work_bas_path = work_dir.join(format!("{}.bas", tool_name));
|
||||||
|
|
||||||
// Baixar do MinIO direto para work dir
|
// Baixar do MinIO direto para work dir
|
||||||
// (isso pressupõe que o DriveMonitor já sincronizou, ou buscamos do S3 aqui)
|
// (isso pressupõe que o DriveMonitor já sincronizou, ou buscamos do S3 aqui)
|
||||||
// Por enquanto, assumimos que o arquivo já está em work dir de sincronização anterior
|
// Por enquanto, assumimos que o arquivo já está em work dir de sincronização anterior
|
||||||
// Se não existir, precisa buscar do S3
|
// Se não existir, precisa buscar do S3
|
||||||
|
|
||||||
if !work_bas_path.exists() {
|
if !work_bas_path.exists() {
|
||||||
// Buscar do S3 - isso deveria ser feito pelo DriveMonitor
|
// Buscar do S3 - isso deveria ser feito pelo DriveMonitor
|
||||||
// Por enquanto, apenas logamos
|
// Por enquanto, apenas logamos
|
||||||
warn!("File {} not found in work dir, skipping", work_bas_path.display());
|
warn!("File {} not found in work dir, skipping", work_bas_path.display());
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ler conteúdo
|
// Ler conteúdo
|
||||||
let content = std::fs::read_to_string(&work_bas_path)?;
|
let content = std::fs::read_to_string(&work_bas_path)?;
|
||||||
|
|
||||||
// Compilar com BasicCompiler (já está no work dir, então compila in-place)
|
// Compilar com BasicCompiler (já está no work dir, então compila in-place)
|
||||||
let mut compiler = BasicCompiler::new(self.state.clone(), bot_id);
|
let mut compiler = BasicCompiler::new(self.state.clone(), bot_id);
|
||||||
compiler.compile_file(
|
compiler.compile_file(
|
||||||
work_bas_path.to_str().ok_or("Invalid path")?,
|
work_bas_path.to_str().ok_or("Invalid path")?,
|
||||||
work_dir.to_str().ok_or("Invalid path")?
|
work_dir.to_str().ok_or("Invalid path")?
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
info!("Compiled {} to {}.ast", file_path, tool_name);
|
info!("Compiled {} to {}.ast", file_path, tool_name);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -176,7 +176,7 @@ pub async fn run_axum_server(
|
||||||
|
|
||||||
#[cfg(feature = "drive")]
|
#[cfg(feature = "drive")]
|
||||||
{
|
{
|
||||||
api_router = api_router.merge(crate::drive::configure());
|
api_router = // drive routes are handled by DriveMonitor, no HTTP routes needed
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "directory")]
|
#[cfg(feature = "directory")]
|
||||||
|
|
@ -200,10 +200,10 @@ pub async fn run_axum_server(
|
||||||
let bot_name = params.get("bot_name").cloned().unwrap_or_default();
|
let bot_name = params.get("bot_name").cloned().unwrap_or_default();
|
||||||
let existing_session_id = params.get("session_id").cloned();
|
let existing_session_id = params.get("session_id").cloned();
|
||||||
let existing_user_id = params.get("user_id").cloned();
|
let existing_user_id = params.get("user_id").cloned();
|
||||||
|
|
||||||
let user_id = existing_user_id.unwrap_or_else(|| uuid::Uuid::new_v4().to_string());
|
let user_id = existing_user_id.unwrap_or_else(|| uuid::Uuid::new_v4().to_string());
|
||||||
let session_id = existing_session_id.unwrap_or_else(|| uuid::Uuid::new_v4().to_string());
|
let session_id = existing_session_id.unwrap_or_else(|| uuid::Uuid::new_v4().to_string());
|
||||||
|
|
||||||
// Create session in DB if it doesn't exist
|
// Create session in DB if it doesn't exist
|
||||||
let session_uuid = match uuid::Uuid::parse_str(&session_id) {
|
let session_uuid = match uuid::Uuid::parse_str(&session_id) {
|
||||||
Ok(uuid) => uuid,
|
Ok(uuid) => uuid,
|
||||||
|
|
@ -213,7 +213,7 @@ pub async fn run_axum_server(
|
||||||
Ok(uuid) => uuid,
|
Ok(uuid) => uuid,
|
||||||
Err(_) => uuid::Uuid::new_v4(),
|
Err(_) => uuid::Uuid::new_v4(),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get bot_id from bot_name
|
// Get bot_id from bot_name
|
||||||
let bot_id = {
|
let bot_id = {
|
||||||
let conn = state.conn.get().ok();
|
let conn = state.conn.get().ok();
|
||||||
|
|
@ -229,13 +229,13 @@ pub async fn run_axum_server(
|
||||||
uuid::Uuid::nil()
|
uuid::Uuid::nil()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Check if session already exists and reuse it
|
// Check if session already exists and reuse it
|
||||||
let mut final_session_id = session_id.clone();
|
let mut final_session_id = session_id.clone();
|
||||||
{
|
{
|
||||||
let mut sm = state.session_manager.lock().await;
|
let mut sm = state.session_manager.lock().await;
|
||||||
sm.get_or_create_anonymous_user(Some(user_uuid)).ok();
|
sm.get_or_create_anonymous_user(Some(user_uuid)).ok();
|
||||||
|
|
||||||
// Get or create session with the specified ID
|
// Get or create session with the specified ID
|
||||||
let session = sm.get_or_create_session_by_id(
|
let session = sm.get_or_create_session_by_id(
|
||||||
session_uuid,
|
session_uuid,
|
||||||
|
|
@ -243,14 +243,14 @@ pub async fn run_axum_server(
|
||||||
bot_id,
|
bot_id,
|
||||||
"Anonymous Chat"
|
"Anonymous Chat"
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Ok(sess) = session {
|
if let Ok(sess) = session {
|
||||||
final_session_id = sess.id.to_string();
|
final_session_id = sess.id.to_string();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
info!("Anonymous auth for bot: {}, session: {}", bot_name, final_session_id);
|
info!("Anonymous auth for bot: {}, session: {}", bot_name, final_session_id);
|
||||||
|
|
||||||
(
|
(
|
||||||
axum::http::StatusCode::OK,
|
axum::http::StatusCode::OK,
|
||||||
Json(serde_json::json!({
|
Json(serde_json::json!({
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue