24eff21aa4
Default to photo name when search term is too short or on the stop list. Search full text index otherwise, which now include names of people (requires reindexing).
148 lines
3.3 KiB
Go
148 lines
3.3 KiB
Go
package workers
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"runtime"
|
|
"runtime/debug"
|
|
"time"
|
|
|
|
"github.com/photoprism/photoprism/internal/config"
|
|
"github.com/photoprism/photoprism/internal/entity"
|
|
"github.com/photoprism/photoprism/internal/mutex"
|
|
"github.com/photoprism/photoprism/internal/photoprism"
|
|
"github.com/photoprism/photoprism/internal/query"
|
|
)
|
|
|
|
// Meta represents a background metadata optimization worker.
|
|
type Meta struct {
|
|
conf *config.Config
|
|
}
|
|
|
|
// NewMeta returns a new Meta worker.
|
|
func NewMeta(conf *config.Config) *Meta {
|
|
return &Meta{conf: conf}
|
|
}
|
|
|
|
// originalsPath returns the original media files path as string.
|
|
func (m *Meta) originalsPath() string {
|
|
return m.conf.OriginalsPath()
|
|
}
|
|
|
|
// Start metadata optimization routine.
|
|
func (m *Meta) Start(delay time.Duration) (err error) {
|
|
defer func() {
|
|
if r := recover(); r != nil {
|
|
err = fmt.Errorf("metadata: %s (panic)\nstack: %s", r, debug.Stack())
|
|
log.Error(err)
|
|
}
|
|
}()
|
|
|
|
if err := mutex.MetaWorker.Start(); err != nil {
|
|
return err
|
|
}
|
|
|
|
defer mutex.MetaWorker.Stop()
|
|
|
|
log.Debugf("metadata: running facial recognition")
|
|
|
|
// Run faces worker.
|
|
if w := photoprism.NewFaces(m.conf); w.Disabled() {
|
|
log.Debugf("metadata: skipping facial recognition")
|
|
} else if err := w.Start(photoprism.FacesOptions{}); err != nil {
|
|
log.Warn(err)
|
|
}
|
|
|
|
log.Debugf("metadata: starting routine check")
|
|
|
|
settings := m.conf.Settings()
|
|
done := make(map[string]bool)
|
|
|
|
limit := 50
|
|
offset := 0
|
|
optimized := 0
|
|
|
|
// Run index optimization.
|
|
for {
|
|
photos, err := query.PhotosCheck(limit, offset, delay)
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if len(photos) == 0 {
|
|
break
|
|
} else if offset == 0 {
|
|
|
|
}
|
|
|
|
for _, photo := range photos {
|
|
if mutex.MetaWorker.Canceled() {
|
|
return errors.New("metadata: check canceled")
|
|
}
|
|
|
|
if done[photo.PhotoUID] {
|
|
continue
|
|
}
|
|
|
|
done[photo.PhotoUID] = true
|
|
|
|
updated, merged, err := photo.Optimize(settings.StackMeta(), settings.StackUUID(), settings.Features.Estimates)
|
|
|
|
if err != nil {
|
|
log.Errorf("metadata: %s (optimize photo)", err)
|
|
} else if updated {
|
|
optimized++
|
|
log.Debugf("metadata: optimized photo %s", photo.String())
|
|
}
|
|
|
|
for _, p := range merged {
|
|
log.Infof("metadata: merged %s", p.PhotoUID)
|
|
done[p.PhotoUID] = true
|
|
}
|
|
}
|
|
|
|
if mutex.MetaWorker.Canceled() {
|
|
return errors.New("metadata: check canceled")
|
|
}
|
|
|
|
offset += limit
|
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
}
|
|
|
|
if optimized > 0 {
|
|
log.Infof("metadata: optimized %d photos", optimized)
|
|
}
|
|
|
|
// Explicitly set quality of photos without primary file to -1.
|
|
if err := query.ResetPhotoQuality(); err != nil {
|
|
log.Warnf("metadata: %s (reset quality)", err.Error())
|
|
}
|
|
|
|
// Run moments worker.
|
|
if w := photoprism.NewMoments(m.conf); w == nil {
|
|
log.Errorf("metadata: failed updating moments")
|
|
} else if err := w.Start(); err != nil {
|
|
log.Warn(err)
|
|
}
|
|
|
|
log.Debugf("metadata: updating photo counts")
|
|
|
|
// Update precalculated photo and file counts.
|
|
if err := entity.UpdatePhotoCounts(); err != nil {
|
|
log.Warnf("metadata: %s (update counts)", err.Error())
|
|
}
|
|
|
|
log.Debugf("metadata: updating preview images")
|
|
|
|
// Update album, subject, and label preview thumbs.
|
|
if err := query.UpdatePreviews(); err != nil {
|
|
log.Errorf("metadata: %s (update previews)", err)
|
|
}
|
|
|
|
// Run garbage collection.
|
|
runtime.GC()
|
|
|
|
return nil
|
|
}
|