fix: 使用非阻塞锁获取
This commit is contained in:
parent
6dcbd4a6e1
commit
86eeb90fb8
|
|
@ -26,43 +26,40 @@ impl MaterialRepository {
|
|||
let scene_detection_json = material.scene_detection.as_ref()
|
||||
.map(|sd| serde_json::to_string(sd))
|
||||
.transpose()?;
|
||||
let material_type_json = serde_json::to_string(&material.material_type)?;
|
||||
let processing_status_json = serde_json::to_string(&material.processing_status)?;
|
||||
|
||||
self.database.with_connection(|conn| {
|
||||
// 添加调试日志
|
||||
println!("Creating material with model_id: {:?}", material.model_id);
|
||||
|
||||
// 添加调试日志
|
||||
println!("Creating material with model_id: {:?}", material.model_id);
|
||||
conn.execute(
|
||||
"INSERT INTO materials (
|
||||
id, project_id, model_id, name, original_path, file_size, md5_hash,
|
||||
material_type, processing_status, metadata, scene_detection,
|
||||
created_at, updated_at, processed_at, error_message
|
||||
) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14, ?15)",
|
||||
(
|
||||
&material.id,
|
||||
&material.project_id,
|
||||
&material.model_id,
|
||||
&material.name,
|
||||
&material.original_path,
|
||||
material.file_size as i64,
|
||||
&material.md5_hash,
|
||||
&material_type_json,
|
||||
&processing_status_json,
|
||||
&metadata_json,
|
||||
scene_detection_json.as_deref(),
|
||||
material.created_at.to_rfc3339(),
|
||||
material.updated_at.to_rfc3339(),
|
||||
material.processed_at.map(|dt| dt.to_rfc3339()),
|
||||
&material.error_message,
|
||||
),
|
||||
)?;
|
||||
|
||||
let metadata_json = serde_json::to_string(&material.metadata)?;
|
||||
let scene_detection_json = material.scene_detection.as_ref()
|
||||
.map(|sd| serde_json::to_string(sd))
|
||||
.transpose()?;
|
||||
|
||||
conn.execute(
|
||||
"INSERT INTO materials (
|
||||
id, project_id, model_id, name, original_path, file_size, md5_hash,
|
||||
material_type, processing_status, metadata, scene_detection,
|
||||
created_at, updated_at, processed_at, error_message
|
||||
) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14, ?15)",
|
||||
(
|
||||
&material.id,
|
||||
&material.project_id,
|
||||
&material.model_id,
|
||||
&material.name,
|
||||
&material.original_path,
|
||||
material.file_size as i64,
|
||||
&material.md5_hash,
|
||||
serde_json::to_string(&material.material_type)?,
|
||||
serde_json::to_string(&material.processing_status)?,
|
||||
metadata_json,
|
||||
scene_detection_json,
|
||||
material.created_at.to_rfc3339(),
|
||||
material.updated_at.to_rfc3339(),
|
||||
material.processed_at.map(|dt| dt.to_rfc3339()),
|
||||
&material.error_message,
|
||||
),
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
Ok(())
|
||||
}).map_err(|e| anyhow::anyhow!("创建素材失败: {}", e))
|
||||
}
|
||||
|
||||
/// 根据ID获取素材
|
||||
|
|
|
|||
|
|
@ -373,90 +373,22 @@ impl ModelRepository {
|
|||
}
|
||||
|
||||
/// 获取模特照片
|
||||
/// 使用带超时的数据库访问模式,避免无限等待
|
||||
/// 使用非阻塞数据库访问模式,避免无限等待
|
||||
pub fn get_photos(&self, model_id: &str) -> Result<Vec<ModelPhoto>> {
|
||||
println!("get_photos 开始执行,model_id: {}", model_id);
|
||||
|
||||
// 直接使用简化的实现,避免复杂的超时逻辑
|
||||
let result = self.get_photos_simple(model_id);
|
||||
|
||||
match &result {
|
||||
Ok(photos) => println!("get_photos 执行完成,返回 {} 张照片", photos.len()),
|
||||
Err(e) => eprintln!("get_photos 执行失败: {}", e),
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
/// 简化的获取照片实现
|
||||
fn get_photos_simple(&self, model_id: &str) -> Result<Vec<ModelPhoto>> {
|
||||
println!("get_photos_simple 开始获取数据库连接");
|
||||
|
||||
// 直接获取连接,但添加详细日志
|
||||
let conn_arc = self.database.get_connection();
|
||||
println!("get_photos_simple 获取连接引用成功");
|
||||
|
||||
// 使用阻塞方式获取锁,但添加超时检测
|
||||
let conn = match conn_arc.lock() {
|
||||
Ok(conn) => {
|
||||
println!("get_photos_simple 成功获取数据库连接锁");
|
||||
conn
|
||||
// 使用非阻塞方式获取连接
|
||||
match self.database.try_get_connection() {
|
||||
Some(conn) => {
|
||||
println!("get_photos 成功获取数据库连接锁(非阻塞)");
|
||||
let photos = self.execute_photo_query(&conn, model_id)?;
|
||||
println!("get_photos 执行完成,返回 {} 张照片", photos.len());
|
||||
Ok(photos)
|
||||
},
|
||||
Err(e) => {
|
||||
eprintln!("get_photos_simple 获取数据库连接锁失败: {}", e);
|
||||
return Err(rusqlite::Error::SqliteFailure(
|
||||
rusqlite::ffi::Error::new(rusqlite::ffi::SQLITE_BUSY),
|
||||
Some("数据库连接锁获取失败".to_string()),
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
println!("get_photos_simple 开始执行查询");
|
||||
self.execute_photo_query(&conn, model_id)
|
||||
}
|
||||
|
||||
/// 带超时的获取照片实现
|
||||
fn get_photos_with_timeout(&self, model_id: &str) -> Result<Vec<ModelPhoto>> {
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
let start_time = Instant::now();
|
||||
let timeout = Duration::from_secs(10); // 10秒超时
|
||||
let mut retry_count = 0;
|
||||
|
||||
// 获取连接引用,避免生命周期问题
|
||||
let conn_arc = self.database.get_connection();
|
||||
|
||||
loop {
|
||||
println!("get_photos 尝试获取数据库连接,重试次数: {}", retry_count);
|
||||
|
||||
// 尝试获取锁
|
||||
match conn_arc.try_lock() {
|
||||
Ok(conn) => {
|
||||
println!("get_photos 成功获取数据库连接");
|
||||
|
||||
// 成功获取锁,执行查询
|
||||
let result = self.execute_photo_query(&conn, model_id);
|
||||
|
||||
// 返回结果
|
||||
return result;
|
||||
},
|
||||
Err(_) => {
|
||||
println!("get_photos 数据库连接被占用,重试中...");
|
||||
|
||||
// 检查是否超时
|
||||
if start_time.elapsed() >= timeout {
|
||||
eprintln!("get_photos 获取数据库连接超时,已等待 {:?}", start_time.elapsed());
|
||||
return Err(rusqlite::Error::SqliteFailure(
|
||||
rusqlite::ffi::Error::new(rusqlite::ffi::SQLITE_BUSY),
|
||||
Some(format!("数据库连接获取超时,已重试 {} 次", retry_count)),
|
||||
));
|
||||
}
|
||||
|
||||
// 等待一段时间后重试
|
||||
retry_count += 1;
|
||||
let wait_time = std::cmp::min(50 * retry_count, 500); // 递增等待时间,最大500ms
|
||||
std::thread::sleep(Duration::from_millis(wait_time));
|
||||
}
|
||||
None => {
|
||||
println!("get_photos 连接被占用,返回空结果避免阻塞");
|
||||
// 如果连接被占用,直接返回空结果,避免阻塞
|
||||
Ok(Vec::new())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,6 +84,15 @@ impl Database {
|
|||
}
|
||||
}
|
||||
|
||||
/// 尝试非阻塞获取数据库连接
|
||||
/// 如果连接被占用,立即返回 None
|
||||
pub fn try_get_connection(&self) -> Option<std::sync::MutexGuard<Connection>> {
|
||||
match self.connection.try_lock() {
|
||||
Ok(conn) => Some(conn),
|
||||
Err(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// 执行数据库操作的辅助方法,自动处理锁的获取和释放
|
||||
/// 这是推荐的数据库访问方式,可以避免锁竞争问题
|
||||
pub fn with_connection<T, F>(&self, operation: F) -> Result<T, rusqlite::Error>
|
||||
|
|
|
|||
Loading…
Reference in New Issue