From 06d2e05ae4dcd54dad8b0d8f21dba8970c307b7f Mon Sep 17 00:00:00 2001 From: Googol Lee Date: Fri, 11 Jul 2025 11:16:41 +0200 Subject: [PATCH] Non-fork face detection, avoiding a race condition. (#1243) * Non-fork face detection, avoiding a race condition. * Update scanner test. --- .../scanner_tasks/face_detection_task.go | 15 ++++---- api/scanner/scanner_test.go | 38 ++++--------------- 2 files changed, 14 insertions(+), 39 deletions(-) diff --git a/api/scanner/scanner_tasks/face_detection_task.go b/api/scanner/scanner_tasks/face_detection_task.go index bca5f0f4..4ca8ee6e 100644 --- a/api/scanner/scanner_tasks/face_detection_task.go +++ b/api/scanner/scanner_tasks/face_detection_task.go @@ -18,14 +18,13 @@ func (t FaceDetectionTask) AfterProcessMedia(ctx scanner_task.TaskContext, media didProcess := len(updatedURLs) > 0 if didProcess && mediaData.Media.Type == models.MediaTypePhoto { - go func(media *models.Media) { - if face_detection.GlobalFaceDetector == nil { - return - } - if err := face_detection.GlobalFaceDetector.DetectFaces(ctx.GetDB(), media); err != nil { - scanner_utils.ScannerError(ctx, "Error detecting faces in image (%s): %s", media.Path, err) - } - }(mediaData.Media) + media := mediaData.Media + if face_detection.GlobalFaceDetector == nil { + return nil + } + if err := face_detection.GlobalFaceDetector.DetectFaces(ctx.GetDB(), media); err != nil { + scanner_utils.ScannerError(ctx, "Error detecting faces in image (%s): %s", media.Path, err) + } } return nil diff --git a/api/scanner/scanner_test.go b/api/scanner/scanner_test.go index 741d7ef2..45534b70 100644 --- a/api/scanner/scanner_test.go +++ b/api/scanner/scanner_test.go @@ -1,14 +1,12 @@ package scanner_test import ( - "context" "fmt" "os" "path/filepath" "slices" "strings" "testing" - "time" "github.com/google/go-cmp/cmp" "github.com/photoview/photoview/api/graphql/models" @@ -178,18 +176,14 @@ func TestFullScan(t *testing.T) { }) t.Run("CheckFaceGroup", func(t *testing.T) { - ctx, done := context.WithTimeout(t.Context(), time.Second*5) - defer done() + var allFaceGroups []*models.FaceGroup + if err := db.Find(&allFaceGroups).Error; err != nil { + t.Fatal("get face groups error:", err) + } - waitFor(ctx, t, time.Second/2, func() bool { - var allFaceGroups []*models.FaceGroup - if err := db.Find(&allFaceGroups).Error; err != nil { - t.Fatal("get face groups error:", err) - return false - } - - return len(allFaceGroups) == len(wantFaceGroups) - }) + if got, want := len(allFaceGroups), len(wantFaceGroups); got != want { + t.Errorf("len(allFaceGroups) = %d, want: %d", got, want) + } }) t.Run("CheckFaces", func(t *testing.T) { @@ -231,24 +225,6 @@ func equalNameWithoutSuffix(a, b string) bool { return true } -func waitFor(ctx context.Context, t *testing.T, interval time.Duration, checkFn func() bool) { - t.Helper() - - ticker := time.NewTicker(interval) - for { - select { - case <-ctx.Done(): - t.Fatal("check timeout") - return - case <-ticker.C: - } - - if checkFn() { - return - } - } -} - func groupMediaWithFaces(medias []*models.ImageFace) [][]string { grouped := make(map[int][]string)