140 lines
3.7 KiB
Go
140 lines
3.7 KiB
Go
package api
|
|
|
|
import (
|
|
"database/sql"
|
|
"encoding/json"
|
|
"fmt"
|
|
"log"
|
|
"net/http"
|
|
|
|
"fuego/pkg/types"
|
|
)
|
|
|
|
// handleSubmitMetadata handles metadata submission from runner
|
|
func (s *Server) handleSubmitMetadata(w http.ResponseWriter, r *http.Request) {
|
|
jobID, err := parseID(r, "jobId")
|
|
if err != nil {
|
|
s.respondError(w, http.StatusBadRequest, err.Error())
|
|
return
|
|
}
|
|
|
|
// Get runner ID from context (set by runnerAuthMiddleware)
|
|
runnerID, ok := r.Context().Value("runner_id").(int64)
|
|
if !ok {
|
|
s.respondError(w, http.StatusUnauthorized, "runner_id not found in context")
|
|
return
|
|
}
|
|
|
|
var metadata types.BlendMetadata
|
|
if err := json.NewDecoder(r.Body).Decode(&metadata); err != nil {
|
|
s.respondError(w, http.StatusBadRequest, "Invalid metadata JSON")
|
|
return
|
|
}
|
|
|
|
// Verify job exists
|
|
var jobUserID int64
|
|
err = s.db.QueryRow("SELECT user_id FROM jobs WHERE id = ?", jobID).Scan(&jobUserID)
|
|
if err == sql.ErrNoRows {
|
|
s.respondError(w, http.StatusNotFound, "Job not found")
|
|
return
|
|
}
|
|
if err != nil {
|
|
s.respondError(w, http.StatusInternalServerError, fmt.Sprintf("Failed to verify job: %v", err))
|
|
return
|
|
}
|
|
|
|
// Find the metadata extraction task for this job
|
|
var taskID int64
|
|
err = s.db.QueryRow(
|
|
`SELECT id FROM tasks WHERE job_id = ? AND task_type = ? AND runner_id = ?`,
|
|
jobID, types.TaskTypeMetadata, runnerID,
|
|
).Scan(&taskID)
|
|
if err == sql.ErrNoRows {
|
|
s.respondError(w, http.StatusNotFound, "Metadata extraction task not found")
|
|
return
|
|
}
|
|
if err != nil {
|
|
s.respondError(w, http.StatusInternalServerError, fmt.Sprintf("Failed to find task: %v", err))
|
|
return
|
|
}
|
|
|
|
// Convert metadata to JSON
|
|
metadataJSON, err := json.Marshal(metadata)
|
|
if err != nil {
|
|
s.respondError(w, http.StatusInternalServerError, "Failed to marshal metadata")
|
|
return
|
|
}
|
|
|
|
// Update job with metadata
|
|
_, err = s.db.Exec(
|
|
`UPDATE jobs SET blend_metadata = ? WHERE id = ?`,
|
|
string(metadataJSON), jobID,
|
|
)
|
|
if err != nil {
|
|
s.respondError(w, http.StatusInternalServerError, fmt.Sprintf("Failed to update job metadata: %v", err))
|
|
return
|
|
}
|
|
|
|
// Mark task as completed
|
|
_, err = s.db.Exec(
|
|
`UPDATE tasks SET status = ?, completed_at = CURRENT_TIMESTAMP WHERE id = ?`,
|
|
types.TaskStatusCompleted, taskID,
|
|
)
|
|
if err != nil {
|
|
log.Printf("Failed to mark metadata task as completed: %v", err)
|
|
}
|
|
|
|
log.Printf("Metadata extracted for job %d: frame_start=%d, frame_end=%d", jobID, metadata.FrameStart, metadata.FrameEnd)
|
|
|
|
s.respondJSON(w, http.StatusOK, map[string]string{"message": "Metadata submitted successfully"})
|
|
}
|
|
|
|
// handleGetJobMetadata retrieves metadata for a job
|
|
func (s *Server) handleGetJobMetadata(w http.ResponseWriter, r *http.Request) {
|
|
userID, err := getUserID(r)
|
|
if err != nil {
|
|
s.respondError(w, http.StatusUnauthorized, err.Error())
|
|
return
|
|
}
|
|
|
|
jobID, err := parseID(r, "id")
|
|
if err != nil {
|
|
s.respondError(w, http.StatusBadRequest, err.Error())
|
|
return
|
|
}
|
|
|
|
// Verify job belongs to user
|
|
var jobUserID int64
|
|
var blendMetadataJSON sql.NullString
|
|
err = s.db.QueryRow(
|
|
`SELECT user_id, blend_metadata FROM jobs WHERE id = ?`,
|
|
jobID,
|
|
).Scan(&jobUserID, &blendMetadataJSON)
|
|
if err == sql.ErrNoRows {
|
|
s.respondError(w, http.StatusNotFound, "Job not found")
|
|
return
|
|
}
|
|
if err != nil {
|
|
s.respondError(w, http.StatusInternalServerError, fmt.Sprintf("Failed to query job: %v", err))
|
|
return
|
|
}
|
|
if jobUserID != userID {
|
|
s.respondError(w, http.StatusForbidden, "Access denied")
|
|
return
|
|
}
|
|
|
|
if !blendMetadataJSON.Valid || blendMetadataJSON.String == "" {
|
|
s.respondJSON(w, http.StatusOK, nil)
|
|
return
|
|
}
|
|
|
|
var metadata types.BlendMetadata
|
|
if err := json.Unmarshal([]byte(blendMetadataJSON.String), &metadata); err != nil {
|
|
s.respondError(w, http.StatusInternalServerError, "Failed to parse metadata")
|
|
return
|
|
}
|
|
|
|
s.respondJSON(w, http.StatusOK, metadata)
|
|
}
|
|
|