Fix unhandled errors and dead code warnings

- Handle validateContent errors in worker.go
- Handle os.Remove errors in worker.go
- Remove dead CheckContent function from floor_handler.go
- Add comment markers for intentionally ignored errors
- Remove unused result variable

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
dindang 2026-07-16 10:32:30 +08:00
parent cb7e595c27
commit 01a579ab9c
4 changed files with 19 additions and 40 deletions

View File

@ -256,7 +256,7 @@ func FloorStatus(w http.ResponseWriter, r *http.Request) {
func FloorOptions(db *sql.DB) http.HandlerFunc { func FloorOptions(db *sql.DB) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
woodFloors, _ := loadFloorOptions(db, "Hardwood") woodFloors, _ := loadFloorOptions(db, "Hardwood") // non-critical: returns empty on error
woodFloors2, _ := loadFloorOptions(db, "Engineered Wood") woodFloors2, _ := loadFloorOptions(db, "Engineered Wood")
tileFloors, _ := loadFloorOptions(db, "Wood-Look Tile") tileFloors, _ := loadFloorOptions(db, "Wood-Look Tile")
vinylFloors, _ := loadFloorOptions(db, "SPC/LVP") vinylFloors, _ := loadFloorOptions(db, "SPC/LVP")
@ -316,34 +316,6 @@ Style: photorealistic, soft natural matte finish, minimal reflections, no mirror
// ── Content Check ───────────────────────────────────────── // ── Content Check ─────────────────────────────────────────
func CheckContent(client *openrouter.Client) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
writeErr(w, 405, "Method not allowed")
return
}
if err := r.ParseMultipartForm(20 << 20); err != nil {
writeJSON(w, 400, map[string]string{"error": err.Error()})
return
}
file, _, _ := r.FormFile("image")
defer file.Close()
os.MkdirAll("uploads", 0755)
tmpPath := filepath.Join("uploads", fmt.Sprintf("check_%d.png", time.Now().UnixNano()))
dst, _ := os.Create(tmpPath)
io.Copy(dst, file)
dst.Close()
ctx, cancel := context.WithTimeout(r.Context(), 15*time.Second)
defer cancel()
passed, score := validateContent(client, ctx, tmpPath)
msg := fmt.Sprintf("✅ Indoor photo score: %d/10", score)
if !passed {
msg = fmt.Sprintf("Non-indoor photo score: %d/10", score)
}
writeJSON(w, 200, map[string]any{"passed": passed, "score": score, "message": msg})
}
}
func validateContent(client *openrouter.Client, ctx context.Context, imagePath string) (bool, int) { func validateContent(client *openrouter.Client, ctx context.Context, imagePath string) (bool, int) {
imgData, err := os.ReadFile(imagePath) imgData, err := os.ReadFile(imagePath)
if err != nil { if err != nil {

View File

@ -79,12 +79,13 @@ func Products(db *sql.DB) http.HandlerFunc {
} }
} }
// Attach variants (same style_name, different sizes) // Attach variants (same style_name, different sizes)
if variants, _ := repository.GetVariantsByStyle(db, sku); len(variants) > 0 { variants, _ := repository.GetVariantsByStyle(db, sku)
if len(variants) > 0 {
product.Variants = variants product.Variants = variants
} }
// Check favorite status and build specs // Check favorite status and build specs
userID := middleware.UserID(r.Context()) userID := middleware.UserID(r.Context())
favMap, _ := repository.GetFavoritedSKUs(db, userID, []string{sku}) favMap, _ := repository.GetFavoritedSKUs(db, userID, []string{sku}) // ok to ignore err: non-critical
product.IsFavorited = favMap[sku] product.IsFavorited = favMap[sku]
// Build specs: main product + variants as size options // Build specs: main product + variants as size options
allVariants := append([]model.Product{*product}, product.Variants...) allVariants := append([]model.Product{*product}, product.Variants...)
@ -139,7 +140,7 @@ func Products(db *sql.DB) http.HandlerFunc {
skus[i] = p.SKU skus[i] = p.SKU
} }
userID := middleware.UserID(r.Context()) userID := middleware.UserID(r.Context())
favSKUs, _ := repository.GetFavoritedSKUs(db, userID, skus) favSKUs, _ := repository.GetFavoritedSKUs(db, userID, skus) // ok to ignore err: non-critical
specCounts := repository.GetSpecCounts(db, skus) specCounts := repository.GetSpecCounts(db, skus)
items := make([]ProductItem, 0, len(prods)) items := make([]ProductItem, 0, len(prods))

View File

@ -2,8 +2,8 @@ package handler
import ( import (
"database/sql" "database/sql"
"fmt"
"floorvisualizer/internal/logger" "floorvisualizer/internal/logger"
"fmt"
"net/http" "net/http"
"floorvisualizer/internal/model" "floorvisualizer/internal/model"

View File

@ -3,8 +3,8 @@ package queue
import ( import (
"context" "context"
"database/sql" "database/sql"
"fmt"
"floorvisualizer/internal/logger" "floorvisualizer/internal/logger"
"fmt"
"os" "os"
"path/filepath" "path/filepath"
"time" "time"
@ -77,7 +77,11 @@ func processJob(ctx context.Context, rdb *redis.Client, client *openrouter.Clien
// Step 0: content check // Step 0: content check
SetJobProgress(jobCtx, rdb, jobID, "check", "Checking content...") SetJobProgress(jobCtx, rdb, jobID, "check", "Checking content...")
logger.Info("[%s] Content check", jobID) logger.Info("[%s] Content check", jobID)
if passed, _ := validateContent(client, jobCtx, inputPath); !passed { passed, score := validateContent(client, jobCtx, inputPath)
if score == 0 {
logger.Warn("[%s] Content check failed (score=0)", jobID)
}
if !passed {
SetJobError(jobCtx, rdb, jobID, "Content check failed: Please upload an indoor room photo") SetJobError(jobCtx, rdb, jobID, "Content check failed: Please upload an indoor room photo")
return return
} }
@ -102,7 +106,7 @@ func processJob(ctx context.Context, rdb *redis.Client, client *openrouter.Clien
logger.Info("[%s] Inpainting: %s + %s", jobID, floor.Name, pattern.Name) logger.Info("[%s] Inpainting: %s + %s", jobID, floor.Name, pattern.Name)
floorPrompt := handler.BuildFloorPromptPublic(*floor, *pattern, room) floorPrompt := handler.BuildFloorPromptPublic(*floor, *pattern, room)
result, err := client.GenerateImageToFile(jobCtx, openrouter.ImageGenerationRequest{ _, err = client.GenerateImageToFile(jobCtx, openrouter.ImageGenerationRequest{
Prompt: floorPrompt, OutputPath: outputPath, InputImagePath: inputPath, Prompt: floorPrompt, OutputPath: outputPath, InputImagePath: inputPath,
MaskImagePath: maskPath, ImageSize: "2K", MaskImagePath: maskPath, ImageSize: "2K",
}) })
@ -112,10 +116,13 @@ func processJob(ctx context.Context, rdb *redis.Client, client *openrouter.Clien
} }
// Clean up intermediate files // Clean up intermediate files
os.Remove(inputPath) if err := os.Remove(inputPath); err != nil {
os.Remove(maskPath) logger.Warn("[%s] Failed to remove input: %v", jobID, err)
}
if err := os.Remove(maskPath); err != nil {
logger.Warn("[%s] Failed to remove mask: %v", jobID, err)
}
_ = result
SetJobResult(jobCtx, rdb, jobID, "/"+filepath.ToSlash(outputPath)) SetJobResult(jobCtx, rdb, jobID, "/"+filepath.ToSlash(outputPath))
logger.Info("[%s] Done", jobID) logger.Info("[%s] Done", jobID)
} }
@ -180,4 +187,3 @@ func base64enc(data []byte) string {
} }
return string(b) return string(b)
} }