Skip to content

Commit

Permalink
Blob fixes (#3599)
Browse files Browse the repository at this point in the history
* Fix error if movie back image blob was not found
* Don't error out if scene cover get fails
* Don't error out on image get fails
* Add debug logging for fs blobs
* Remove old blob data when no longer referenced
  • Loading branch information
WithoutPants authored Mar 25, 2023
1 parent 0050e4a commit 046fd1c
Show file tree
Hide file tree
Showing 20 changed files with 107 additions and 33 deletions.
6 changes: 3 additions & 3 deletions internal/api/resolver_model_movie.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,10 @@ func (r *movieResolver) FrontImagePath(ctx context.Context, obj *models.Movie) (

func (r *movieResolver) BackImagePath(ctx context.Context, obj *models.Movie) (*string, error) {
// don't return any thing if there is no back image
var img []byte
hasImage := false
if err := r.withReadTxn(ctx, func(ctx context.Context) error {
var err error
img, err = r.repository.Movie.GetBackImage(ctx, obj.ID)
hasImage, err = r.repository.Movie.HasBackImage(ctx, obj.ID)
if err != nil {
return err
}
Expand All @@ -106,7 +106,7 @@ func (r *movieResolver) BackImagePath(ctx context.Context, obj *models.Movie) (*
return nil, err
}

if img == nil {
if !hasImage {
return nil, nil
}

Expand Down
3 changes: 2 additions & 1 deletion internal/api/resolver_mutation_stash_box.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/stashapp/stash/internal/manager"
"github.com/stashapp/stash/internal/manager/config"
"github.com/stashapp/stash/pkg/logger"
"github.com/stashapp/stash/pkg/scraper/stashbox"
)

Expand Down Expand Up @@ -64,7 +65,7 @@ func (r *mutationResolver) SubmitStashBoxSceneDraft(ctx context.Context, input S

cover, err := qb.GetCover(ctx, id)
if err != nil {
return fmt.Errorf("getting scene cover: %w", err)
logger.Errorf("Error getting scene cover: %v", err)
}

res, err = client.SubmitSceneDraft(ctx, scene, boxes[input.StashBoxIndex].Endpoint, cover)
Expand Down
3 changes: 2 additions & 1 deletion internal/identify/scene.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"strings"
"time"

"github.com/stashapp/stash/pkg/logger"
"github.com/stashapp/stash/pkg/models"
"github.com/stashapp/stash/pkg/scene"
"github.com/stashapp/stash/pkg/sliceutil"
Expand Down Expand Up @@ -234,7 +235,7 @@ func (g sceneRelationships) cover(ctx context.Context) ([]byte, error) {
// always overwrite if present
existingCover, err := g.sceneReader.GetCover(ctx, g.scene.ID)
if err != nil {
return nil, fmt.Errorf("error getting scene cover: %w", err)
logger.Errorf("Error getting scene cover: %v", err)
}

data, err := utils.ProcessImageInput(ctx, *scraped)
Expand Down
4 changes: 2 additions & 2 deletions internal/identify/scene_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -742,8 +742,8 @@ func Test_sceneRelationships_cover(t *testing.T) {
"error getting scene cover",
errSceneID,
&newDataEncoded,
nil,
true,
newData,
false,
},
{
"invalid data",
Expand Down
5 changes: 2 additions & 3 deletions internal/manager/running_streams.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,8 @@ func (s *SceneServer) ServeScreenshot(scene *models.Scene, w http.ResponseWriter

var cover []byte
readTxnErr := txn.WithReadTxn(r.Context(), s.TxnManager, func(ctx context.Context) error {
var err error
cover, err = s.SceneCoverGetter.GetCover(ctx, scene.ID)
return err
cover, _ = s.SceneCoverGetter.GetCover(ctx, scene.ID)
return nil
})
if errors.Is(readTxnErr, context.Canceled) {
return
Expand Down
21 changes: 21 additions & 0 deletions pkg/models/mocks/MovieReaderWriter.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pkg/models/movie.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ type MovieReader interface {
Query(ctx context.Context, movieFilter *MovieFilterType, findFilter *FindFilterType) ([]*Movie, int, error)
GetFrontImage(ctx context.Context, movieID int) ([]byte, error)
GetBackImage(ctx context.Context, movieID int) ([]byte, error)
HasBackImage(ctx context.Context, movieID int) (bool, error)
FindByPerformerID(ctx context.Context, performerID int) ([]*Movie, error)
CountByPerformerID(ctx context.Context, performerID int) (int, error)
FindByStudioID(ctx context.Context, studioID int) ([]*Movie, error)
Expand Down
5 changes: 3 additions & 2 deletions pkg/movie/export.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"fmt"

"github.com/stashapp/stash/pkg/logger"
"github.com/stashapp/stash/pkg/models"
"github.com/stashapp/stash/pkg/models/json"
"github.com/stashapp/stash/pkg/models/jsonschema"
Expand Down Expand Up @@ -64,7 +65,7 @@ func ToJSON(ctx context.Context, reader ImageGetter, studioReader studio.Finder,

frontImage, err := reader.GetFrontImage(ctx, movie.ID)
if err != nil {
return nil, fmt.Errorf("error getting movie front image: %v", err)
logger.Errorf("Error getting movie front image: %v", err)
}

if len(frontImage) > 0 {
Expand All @@ -73,7 +74,7 @@ func ToJSON(ctx context.Context, reader ImageGetter, studioReader studio.Finder,

backImage, err := reader.GetBackImage(ctx, movie.ID)
if err != nil {
return nil, fmt.Errorf("error getting movie back image: %v", err)
logger.Errorf("Error getting movie back image: %v", err)
}

if len(backImage) > 0 {
Expand Down
10 changes: 6 additions & 4 deletions pkg/movie/export_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,13 +161,15 @@ func initTestTable() {
},
{
createFullMovie(errFrontImageID, studioID),
nil,
true,
createFullJSONMovie(studioName, "", backImage),
// failure to get front image should not cause error
false,
},
{
createFullMovie(errBackImageID, studioID),
nil,
true,
createFullJSONMovie(studioName, frontImage, ""),
// failure to get back image should not cause error
false,
},
{
createFullMovie(errStudioMovieID, errStudioID),
Expand Down
3 changes: 2 additions & 1 deletion pkg/performer/export.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"strconv"

"github.com/stashapp/stash/pkg/logger"
"github.com/stashapp/stash/pkg/models"
"github.com/stashapp/stash/pkg/models/json"
"github.com/stashapp/stash/pkg/models/jsonschema"
Expand Down Expand Up @@ -74,7 +75,7 @@ func ToJSON(ctx context.Context, reader ImageAliasStashIDGetter, performer *mode

image, err := reader.GetImage(ctx, performer.ID)
if err != nil {
return nil, fmt.Errorf("getting performers image: %w", err)
logger.Errorf("Error getting performer image: %v", err)
}

if len(image) > 0 {
Expand Down
5 changes: 3 additions & 2 deletions pkg/performer/export_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,8 +185,9 @@ func initTestTable() {
},
{
*createFullPerformer(errImageID, performerName),
nil,
true,
createFullJSONPerformer(performerName, ""),
// failure to get image should not cause an error
false,
},
}
}
Expand Down
3 changes: 2 additions & 1 deletion pkg/scene/export.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"math"
"strconv"

"github.com/stashapp/stash/pkg/logger"
"github.com/stashapp/stash/pkg/models"
"github.com/stashapp/stash/pkg/models/json"
"github.com/stashapp/stash/pkg/models/jsonschema"
Expand Down Expand Up @@ -64,7 +65,7 @@ func ToBasicJSON(ctx context.Context, reader CoverGetter, scene *models.Scene) (

cover, err := reader.GetCover(ctx, scene.ID)
if err != nil {
return nil, fmt.Errorf("error getting scene cover: %v", err)
logger.Errorf("Error getting scene cover: %v", err)
}

if len(cover) > 0 {
Expand Down
5 changes: 3 additions & 2 deletions pkg/scene/export_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,9 @@ var scenarios = []basicTestScenario{
},
{
createFullScene(errImageID),
nil,
true,
createFullJSONScene(""),
// failure to get image should not cause an error
false,
},
}

Expand Down
42 changes: 37 additions & 5 deletions pkg/sqlite/blob.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/mattn/go-sqlite3"
"github.com/stashapp/stash/pkg/file"
"github.com/stashapp/stash/pkg/hash/md5"
"github.com/stashapp/stash/pkg/logger"
"github.com/stashapp/stash/pkg/sqlite/blob"
"github.com/stashapp/stash/pkg/utils"
"gopkg.in/guregu/null.v4"
Expand Down Expand Up @@ -268,6 +269,7 @@ func (qb *BlobStore) Delete(ctx context.Context, checksum string) error {
if err := qb.delete(ctx, checksum); err != nil {
if qb.isConstraintError(err) {
// blob is still referenced - do not delete
logger.Debugf("Blob %s is still referenced - not deleting", checksum)
return nil
}

Expand All @@ -277,6 +279,7 @@ func (qb *BlobStore) Delete(ctx context.Context, checksum string) error {

// blob was deleted from the database - delete from filesystem if enabled
if qb.options.UseFilesystem {
logger.Debugf("Deleting blob %s from filesystem", checksum)
if err := qb.fsStore.Delete(ctx, checksum); err != nil {
return fmt.Errorf("deleting from filesystem: %w", err)
}
Expand Down Expand Up @@ -330,17 +333,33 @@ func (qb *blobJoinQueryBuilder) UpdateImage(ctx context.Context, id int, blobCol
if len(image) == 0 {
return qb.DestroyImage(ctx, id, blobCol)
}

oldChecksum, err := qb.getChecksum(ctx, id, blobCol)
if err != nil {
return err
}

checksum, err := qb.blobStore.Write(ctx, image)
if err != nil {
return err
}

sqlQuery := fmt.Sprintf("UPDATE %s SET %s = ? WHERE id = ?", qb.joinTable, blobCol)
_, err = qb.tx.Exec(ctx, sqlQuery, checksum, id)
return err
if _, err := qb.tx.Exec(ctx, sqlQuery, checksum, id); err != nil {
return err
}

// #3595 - delete the old blob if the checksum is different
if oldChecksum != nil && *oldChecksum != checksum {
if err := qb.blobStore.Delete(ctx, *oldChecksum); err != nil {
return err
}
}

return nil
}

func (qb *blobJoinQueryBuilder) DestroyImage(ctx context.Context, id int, blobCol string) error {
func (qb *blobJoinQueryBuilder) getChecksum(ctx context.Context, id int, blobCol string) (*string, error) {
sqlQuery := utils.StrFormat(`
SELECT {joinTable}.{joinCol} FROM {joinTable} WHERE {joinTable}.id = ?
`, utils.StrFormatMap{
Expand All @@ -351,10 +370,23 @@ SELECT {joinTable}.{joinCol} FROM {joinTable} WHERE {joinTable}.id = ?
var checksum null.String
err := qb.repository.querySimple(ctx, sqlQuery, []interface{}{id}, &checksum)
if err != nil {
return err
return nil, err
}

if !checksum.Valid {
return nil, nil
}

return &checksum.String, nil
}

func (qb *blobJoinQueryBuilder) DestroyImage(ctx context.Context, id int, blobCol string) error {
checksum, err := qb.getChecksum(ctx, id, blobCol)
if err != nil {
return err
}

if checksum == nil {
// no image to delete
return nil
}
Expand All @@ -364,7 +396,7 @@ SELECT {joinTable}.{joinCol} FROM {joinTable} WHERE {joinTable}.id = ?
return err
}

return qb.blobStore.Delete(ctx, checksum.String)
return qb.blobStore.Delete(ctx, *checksum)
}

func (qb *blobJoinQueryBuilder) HasImage(ctx context.Context, id int, blobCol string) (bool, error) {
Expand Down
2 changes: 2 additions & 0 deletions pkg/sqlite/blob/fs.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (

"github.com/stashapp/stash/pkg/file"
"github.com/stashapp/stash/pkg/fsutil"
"github.com/stashapp/stash/pkg/logger"
)

const (
Expand Down Expand Up @@ -61,6 +62,7 @@ func (s *FilesystemStore) Write(ctx context.Context, checksum string, data []byt
return fmt.Errorf("creating directory %q: %w", filepath.Dir(fn), err)
}

logger.Debugf("Writing blob file %s", fn)
out, err := s.fs.Create(fn)
if err != nil {
return fmt.Errorf("creating file %q: %w", fn, err)
Expand Down
4 changes: 4 additions & 0 deletions pkg/sqlite/movies.go
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,10 @@ func (qb *movieQueryBuilder) GetBackImage(ctx context.Context, movieID int) ([]b
return qb.GetImage(ctx, movieID, movieBackImageBlobColumn)
}

func (qb *movieQueryBuilder) HasBackImage(ctx context.Context, movieID int) (bool, error) {
return qb.HasImage(ctx, movieID, movieBackImageBlobColumn)
}

func (qb *movieQueryBuilder) FindByPerformerID(ctx context.Context, performerID int) ([]*models.Movie, error) {
query := `SELECT DISTINCT movies.*
FROM movies
Expand Down
3 changes: 2 additions & 1 deletion pkg/studio/export.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"fmt"

"github.com/stashapp/stash/pkg/logger"
"github.com/stashapp/stash/pkg/models"
"github.com/stashapp/stash/pkg/models/json"
"github.com/stashapp/stash/pkg/models/jsonschema"
Expand Down Expand Up @@ -61,7 +62,7 @@ func ToJSON(ctx context.Context, reader FinderImageStashIDGetter, studio *models

image, err := reader.GetImage(ctx, studio.ID)
if err != nil {
return nil, fmt.Errorf("error getting studio image: %v", err)
logger.Errorf("Error getting studio image: %v", err)
}

if len(image) > 0 {
Expand Down
6 changes: 4 additions & 2 deletions pkg/studio/export_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,9 @@ func initTestTable() {
},
{
createFullStudio(errImageID, parentStudioID),
nil,
true,
createFullJSONStudio(parentStudioName, "", nil),
// failure to get image is not an error
false,
},
{
createFullStudio(missingParentStudioID, missingStudioID),
Expand Down Expand Up @@ -200,6 +201,7 @@ func TestToJSON(t *testing.T) {
mockStudioReader.On("GetStashIDs", ctx, studioID).Return(stashIDs, nil).Once()
mockStudioReader.On("GetStashIDs", ctx, noImageID).Return(nil, nil).Once()
mockStudioReader.On("GetStashIDs", ctx, missingParentStudioID).Return(stashIDs, nil).Once()
mockStudioReader.On("GetStashIDs", ctx, errImageID).Return(stashIDs, nil).Once()

for i, s := range scenarios {
studio := s.input
Expand Down
3 changes: 2 additions & 1 deletion pkg/tag/export.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"fmt"

"github.com/stashapp/stash/pkg/logger"
"github.com/stashapp/stash/pkg/models"
"github.com/stashapp/stash/pkg/models/json"
"github.com/stashapp/stash/pkg/models/jsonschema"
Expand Down Expand Up @@ -35,7 +36,7 @@ func ToJSON(ctx context.Context, reader FinderAliasImageGetter, tag *models.Tag)

image, err := reader.GetImage(ctx, tag.ID)
if err != nil {
return nil, fmt.Errorf("error getting tag image: %v", err)
logger.Errorf("Error getting tag image: %v", err)
}

if len(image) > 0 {
Expand Down
Loading

0 comments on commit 046fd1c

Please sign in to comment.