From 4ac0ef35564cb394d3dc96f7d28a1874260af95b Mon Sep 17 00:00:00 2001 From: Michael Mayer Date: Sun, 27 Dec 2020 07:43:39 +0100 Subject: [PATCH] Indexer: Improve merging and performance Signed-off-by: Michael Mayer --- internal/entity/photo_merge.go | 21 +++++++++++---------- internal/entity/photo_quality.go | 11 +++++++++++ internal/photoprism/index_mediafile.go | 18 ++++++------------ 3 files changed, 28 insertions(+), 22 deletions(-) diff --git a/internal/entity/photo_merge.go b/internal/entity/photo_merge.go index 904df5aae..eaf2dc3f5 100644 --- a/internal/entity/photo_merge.go +++ b/internal/entity/photo_merge.go @@ -1,10 +1,14 @@ package entity import ( + "sync" + "github.com/jinzhu/gorm" "github.com/photoprism/photoprism/pkg/rnd" ) +var photoMergeMutex = sync.Mutex{} + // ResolvePrimary ensures there is only one primary file for a photo. func (m *Photo) ResolvePrimary() error { var file File @@ -29,7 +33,7 @@ func (m *Photo) Identical(includeMeta, includeUuid bool) (identical Photos, err "OR (uuid = ? AND photo_stack > -1)"+ "OR (photo_path = ? AND photo_name = ?)", m.TakenAt, m.CellID, m.CameraSerial, m.CameraID, m.UUID, m.PhotoPath, m.PhotoName). - Order("id ASC").Find(&identical).Error; err != nil { + Order("photo_quality DESC, id ASC").Find(&identical).Error; err != nil { return identical, err } case includeMeta && m.HasLocation() && m.HasLatLng() && m.TakenSrc == SrcMeta: @@ -37,20 +41,20 @@ func (m *Photo) Identical(includeMeta, includeUuid bool) (identical Photos, err Where("(taken_at = ? AND taken_src = 'meta' AND photo_stack > -1 AND cell_id = ? AND camera_serial = ? AND camera_id = ?) "+ "OR (photo_path = ? AND photo_name = ?)", m.TakenAt, m.CellID, m.CameraSerial, m.CameraID, m.PhotoPath, m.PhotoName). - Order("id ASC").Find(&identical).Error; err != nil { + Order("photo_quality DESC, id ASC").Find(&identical).Error; err != nil { return identical, err } case includeUuid && rnd.IsUUID(m.UUID): if err := Db(). Where("(uuid = ? AND photo_stack > -1) OR (photo_path = ? AND photo_name = ?)", m.UUID, m.PhotoPath, m.PhotoName). - Order("id ASC").Find(&identical).Error; err != nil { + Order("photo_quality DESC, id ASC").Find(&identical).Error; err != nil { return identical, err } default: if err := Db(). Where("photo_path = ? AND photo_name = ?", m.PhotoPath, m.PhotoName). - Order("id ASC").Find(&identical).Error; err != nil { + Order("photo_quality DESC, id ASC").Find(&identical).Error; err != nil { return identical, err } } @@ -60,6 +64,9 @@ func (m *Photo) Identical(includeMeta, includeUuid bool) (identical Photos, err // Merge photo with identical ones. func (m *Photo) Merge(mergeMeta, mergeUuid bool) (original Photo, merged Photos, err error) { + photoMergeMutex.Lock() + defer photoMergeMutex.Unlock() + identical, err := m.Identical(mergeMeta, mergeUuid) if len(identical) < 2 || err != nil { @@ -110,11 +117,5 @@ func (m *Photo) Merge(mergeMeta, mergeUuid bool) (original Photo, merged Photos, m.PhotoQuality = -1 } - original.PhotoQuality = original.QualityScore() - - if err := original.Save(); err != nil { - log.Errorf("photo: %s in %s (merge)", err, original.PhotoName) - } - return original, merged, err } diff --git a/internal/entity/photo_quality.go b/internal/entity/photo_quality.go index 8528f58b0..3805ae9b9 100644 --- a/internal/entity/photo_quality.go +++ b/internal/entity/photo_quality.go @@ -67,3 +67,14 @@ func (m *Photo) QualityScore() (score int) { return score } + +// UpdateQuality updates the photo quality attribute. +func (m *Photo) UpdateQuality() error { + if m.DeletedAt != nil || m.PhotoQuality < 0 { + return nil + } + + m.PhotoQuality = m.QualityScore() + + return m.Update("PhotoQuality", m.PhotoQuality) +} diff --git a/internal/photoprism/index_mediafile.go b/internal/photoprism/index_mediafile.go index e1e829392..706f1f407 100644 --- a/internal/photoprism/index_mediafile.go +++ b/internal/photoprism/index_mediafile.go @@ -749,7 +749,7 @@ func (ind *Index) MediaFile(m *MediaFile, o IndexOptions, originalName string) ( photo.PhotoQuality = photo.QualityScore() if err := photo.Save(); err != nil { - log.Errorf("index: %s in %s (update photo metadata)", err, logName) + log.Errorf("index: %s in %s (update metadata)", err, logName) result.Status = IndexFailed result.Err = err return result @@ -762,17 +762,11 @@ func (ind *Index) MediaFile(m *MediaFile, o IndexOptions, originalName string) ( if err := photo.IndexKeywords(); err != nil { log.Errorf("index: %s in %s (save keywords)", err, logName) } - } else if photo.DeletedAt == nil { - if photo.PhotoQuality >= 0 { - photo.PhotoQuality = photo.QualityScore() - } - - if err := photo.Save(); err != nil { - log.Errorf("index: %s in %s (update photo quality)", err, logName) - result.Status = IndexFailed - result.Err = err - return result - } + } else if err := photo.UpdateQuality(); err != nil { + log.Errorf("index: %s in %s (update quality)", err, logName) + result.Status = IndexFailed + result.Err = err + return result } result.Status = IndexUpdated