2cfcfdd1af
Phase 2.6.1: co_occurrence_edges migration - build_co_occurrence_edges_from_qdrant() - Qdrant embeddings → frame grouping → YOLO objects - Result: 6679 edges (vs 6701 PostgreSQL) Phase 2.6.2: face_face_edges migration - build_face_face_edges_from_qdrant() - Qdrant embeddings → frame grouping → face pairs - mutual_gaze detection preserved - Result: 6 edges (exact match) Phase 2.6.3: speaker_face_edges migration - build_speaker_face_edges_from_qdrant() - Qdrant embeddings → trace_id frame ranges - SPEAKS_AS edge creation Architecture: - All edges use Qdrant payload (no face_detections queries) - PostgreSQL fallback for empty Qdrant - Estimated 3.6x performance improvement Testing: - Playground (3003): ✓ All Phase 2.6 logs verified - Edge counts: ✓ Close match with PostgreSQL - Fallback: ✓ Working Docs: - docs_v1.0/DESIGN/TKG_PHASE2_6_EDGES_MIGRATION.md - docs_v1.0/M4_workspace/2026-06-21_phase2_6_test.md
120 lines
3.5 KiB
Rust
120 lines
3.5 KiB
Rust
use axum::{
|
|
extract::{Path, State},
|
|
http::StatusCode,
|
|
routing::{get, post},
|
|
Json, Router,
|
|
};
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
use crate::api::types::AppState;
|
|
use crate::core::checkin;
|
|
use crate::core::db::VideoStatus;
|
|
|
|
#[derive(Debug, Serialize)]
|
|
struct CheckinResponse {
|
|
file_uuid: String,
|
|
pre_chunks_moved: usize,
|
|
speaker_detections_moved: usize,
|
|
vectors_moved: usize,
|
|
status: String,
|
|
}
|
|
|
|
#[derive(Debug, Serialize)]
|
|
struct CheckoutResponse {
|
|
file_uuid: String,
|
|
rows_deleted: usize,
|
|
status: String,
|
|
}
|
|
|
|
#[derive(Debug, Serialize)]
|
|
struct WorkspaceStatusResponse {
|
|
file_uuid: String,
|
|
exists: bool,
|
|
}
|
|
|
|
async fn checkin_handler(
|
|
State(state): State<AppState>,
|
|
Path(file_uuid): Path<String>,
|
|
) -> Result<Json<CheckinResponse>, (StatusCode, Json<serde_json::Value>)> {
|
|
match checkin::checkin(&state.db, &file_uuid).await {
|
|
Ok(result) => {
|
|
if let Err(e) = state
|
|
.db
|
|
.update_video_status(&file_uuid, VideoStatus::Indexed)
|
|
.await
|
|
{
|
|
tracing::warn!(
|
|
"Failed to update video status to Indexed for {}: {}",
|
|
file_uuid,
|
|
e
|
|
);
|
|
}
|
|
Ok(Json(CheckinResponse {
|
|
file_uuid: result.file_uuid.clone(),
|
|
pre_chunks_moved: result.pre_chunks_moved,
|
|
speaker_detections_moved: result.speaker_detections_moved,
|
|
vectors_moved: result.vectors_moved,
|
|
status: "indexed".to_string(),
|
|
}))
|
|
}
|
|
Err(e) => Err((
|
|
StatusCode::INTERNAL_SERVER_ERROR,
|
|
Json(serde_json::json!({
|
|
"error": format!("Checkin failed: {}", e),
|
|
"file_uuid": file_uuid,
|
|
})),
|
|
)),
|
|
}
|
|
}
|
|
|
|
async fn checkout_handler(
|
|
State(state): State<AppState>,
|
|
Path(file_uuid): Path<String>,
|
|
) -> Result<Json<CheckoutResponse>, (StatusCode, Json<serde_json::Value>)> {
|
|
match checkin::checkout(&state.db, &file_uuid).await {
|
|
Ok(result) => {
|
|
if let Err(e) = state
|
|
.db
|
|
.update_video_status(&file_uuid, VideoStatus::CheckedOut)
|
|
.await
|
|
{
|
|
tracing::warn!(
|
|
"Failed to update video status to CheckedOut for {}: {}",
|
|
file_uuid,
|
|
e
|
|
);
|
|
}
|
|
Ok(Json(CheckoutResponse {
|
|
file_uuid: result.file_uuid.clone(),
|
|
rows_deleted: result.rows_deleted,
|
|
status: "checked_out".to_string(),
|
|
}))
|
|
}
|
|
Err(e) => Err((
|
|
StatusCode::INTERNAL_SERVER_ERROR,
|
|
Json(serde_json::json!({
|
|
"error": format!("Checkout failed: {}", e),
|
|
"file_uuid": file_uuid,
|
|
})),
|
|
)),
|
|
}
|
|
}
|
|
|
|
async fn workspace_status_handler(Path(file_uuid): Path<String>) -> Json<WorkspaceStatusResponse> {
|
|
use crate::core::db::workspace_sqlite::WorkspaceDb;
|
|
Json(WorkspaceStatusResponse {
|
|
file_uuid: file_uuid.clone(),
|
|
exists: WorkspaceDb::exists(&file_uuid),
|
|
})
|
|
}
|
|
|
|
pub fn checkin_routes() -> Router<AppState> {
|
|
Router::new()
|
|
.route("/api/v1/file/:file_uuid/checkin", post(checkin_handler))
|
|
.route("/api/v1/file/:file_uuid/checkout", post(checkout_handler))
|
|
.route(
|
|
"/api/v1/file/:file_uuid/workspace",
|
|
get(workspace_status_handler),
|
|
)
|
|
}
|