[Files Refactor] Performance tuning (#2865)

* Don't load image files by default
* Don't load gallery files by default
* Don't load scene files by default
* Retry locked transactions forever
* Don't show release notes if config not loaded
* Don't translate path slashes in export
This commit is contained in:
WithoutPants
2022-09-01 17:54:34 +10:00
parent 0b534d89c6
commit 273cf0383d
94 changed files with 2611 additions and 981 deletions

View File

@@ -2,6 +2,7 @@ package models
import (
"context"
"errors"
"path/filepath"
"strconv"
"time"
@@ -22,7 +23,14 @@ type Scene struct {
StudioID *int `json:"studio_id"`
// transient - not persisted
Files []*file.VideoFile
Files RelatedVideoFiles
PrimaryFileID *file.ID
// transient - path of primary file - empty if no files
Path string
// transient - oshash of primary file - empty if no files
OSHash string
// transient - checksum of primary file - empty if no files
Checksum string
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
@@ -34,6 +42,35 @@ type Scene struct {
StashIDs RelatedStashIDs `json:"stash_ids"`
}
func (s *Scene) LoadFiles(ctx context.Context, l VideoFileLoader) error {
return s.Files.load(func() ([]*file.VideoFile, error) {
return l.GetFiles(ctx, s.ID)
})
}
func (s *Scene) LoadPrimaryFile(ctx context.Context, l file.Finder) error {
return s.Files.loadPrimary(func() (*file.VideoFile, error) {
if s.PrimaryFileID == nil {
return nil, nil
}
f, err := l.Find(ctx, *s.PrimaryFileID)
if err != nil {
return nil, err
}
var vf *file.VideoFile
if len(f) > 0 {
var ok bool
vf, ok = f[0].(*file.VideoFile)
if !ok {
return nil, errors.New("not a video file")
}
}
return vf, nil
})
}
func (s *Scene) LoadGalleryIDs(ctx context.Context, l GalleryIDLoader) error {
return s.GalleryIDs.load(func() ([]int, error) {
return l.GetGalleryIDs(ctx, s.ID)
@@ -85,89 +122,13 @@ func (s *Scene) LoadRelationships(ctx context.Context, l SceneReader) error {
return err
}
if err := s.LoadFiles(ctx, l); err != nil {
return err
}
return nil
}
func (s Scene) PrimaryFile() *file.VideoFile {
if len(s.Files) == 0 {
return nil
}
return s.Files[0]
}
func (s Scene) Path() string {
if p := s.PrimaryFile(); p != nil {
return p.Base().Path
}
return ""
}
func (s Scene) getHash(type_ string) string {
if p := s.PrimaryFile(); p != nil {
v := p.Base().Fingerprints.Get(type_)
if v == nil {
return ""
}
return v.(string)
}
return ""
}
func (s Scene) Checksum() string {
return s.getHash(file.FingerprintTypeMD5)
}
func (s Scene) OSHash() string {
return s.getHash(file.FingerprintTypeOshash)
}
func (s Scene) Phash() int64 {
if p := s.PrimaryFile(); p != nil {
v := p.Base().Fingerprints.Get(file.FingerprintTypePhash)
if v == nil {
return 0
}
return v.(int64)
}
return 0
}
func (s Scene) Duration() float64 {
if p := s.PrimaryFile(); p != nil {
return p.Duration
}
return 0
}
func (s Scene) Format() string {
if p := s.PrimaryFile(); p != nil {
return p.Format
}
return ""
}
func (s Scene) VideoCodec() string {
if p := s.PrimaryFile(); p != nil {
return p.VideoCodec
}
return ""
}
func (s Scene) AudioCodec() string {
if p := s.PrimaryFile(); p != nil {
return p.AudioCodec
}
return ""
}
// ScenePartial represents part of a Scene object. It is used to update
// the database entry.
type ScenePartial struct {
@@ -258,43 +219,22 @@ func (s Scene) GetTitle() string {
return s.Title
}
return filepath.Base(s.Path())
return filepath.Base(s.Path)
}
// GetHash returns the hash of the scene, based on the hash algorithm provided. If
// hash algorithm is MD5, then Checksum is returned. Otherwise, OSHash is returned.
func (s Scene) GetHash(hashAlgorithm HashAlgorithm) string {
f := s.PrimaryFile()
if f == nil {
return ""
}
switch hashAlgorithm {
case HashAlgorithmMd5:
return f.Base().Fingerprints.Get(file.FingerprintTypeMD5).(string)
return s.Checksum
case HashAlgorithmOshash:
return f.Base().Fingerprints.Get(file.FingerprintTypeOshash).(string)
return s.OSHash
}
return ""
}
func (s Scene) GetMinResolution() int {
f := s.PrimaryFile()
if f == nil {
return 0
}
w := f.Width
h := f.Height
if w < h {
return w
}
return h
}
// SceneFileType represents the file metadata for a scene.
type SceneFileType struct {
Size *string `graphql:"size" json:"size"`