mirror of
https://github.com/stashapp/stash.git
synced 2025-12-18 04:44:37 +03:00
Fix database locked errors (#3153)
* Make read-only operations use WithReadTxn * Allow one database write thread * Add unit test for concurrent transactions * Perform some actions after commit to release txn * Suppress some errors from cancelled context
This commit is contained in:
@@ -73,26 +73,6 @@ func (h *ScanHandler) validate() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *ScanHandler) logInfo(ctx context.Context, format string, args ...interface{}) {
|
||||
// log at the end so that if anything fails above due to a locked database
|
||||
// error and the transaction must be retried, then we shouldn't get multiple
|
||||
// logs of the same thing.
|
||||
txn.AddPostCompleteHook(ctx, func(ctx context.Context) error {
|
||||
logger.Infof(format, args...)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (h *ScanHandler) logError(ctx context.Context, format string, args ...interface{}) {
|
||||
// log at the end so that if anything fails above due to a locked database
|
||||
// error and the transaction must be retried, then we shouldn't get multiple
|
||||
// logs of the same thing.
|
||||
txn.AddPostCompleteHook(ctx, func(ctx context.Context) error {
|
||||
logger.Errorf(format, args...)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (h *ScanHandler) Handle(ctx context.Context, f file.File, oldFile file.File) error {
|
||||
if err := h.validate(); err != nil {
|
||||
return err
|
||||
@@ -132,7 +112,7 @@ func (h *ScanHandler) Handle(ctx context.Context, f file.File, oldFile file.File
|
||||
GalleryIDs: models.NewRelatedIDs([]int{}),
|
||||
}
|
||||
|
||||
h.logInfo(ctx, "%s doesn't exist. Creating new image...", f.Base().Path)
|
||||
logger.Infof("%s doesn't exist. Creating new image...", f.Base().Path)
|
||||
|
||||
if _, err := h.associateGallery(ctx, newImage, imageFile); err != nil {
|
||||
return err
|
||||
@@ -162,12 +142,17 @@ func (h *ScanHandler) Handle(ctx context.Context, f file.File, oldFile file.File
|
||||
}
|
||||
|
||||
if h.ScanConfig.IsGenerateThumbnails() {
|
||||
for _, s := range existing {
|
||||
if err := h.ThumbnailGenerator.GenerateThumbnail(ctx, s, imageFile); err != nil {
|
||||
// just log if cover generation fails. We can try again on rescan
|
||||
h.logError(ctx, "Error generating thumbnail for %s: %v", imageFile.Path, err)
|
||||
// do this after the commit so that the transaction isn't held up
|
||||
txn.AddPostCommitHook(ctx, func(ctx context.Context) error {
|
||||
for _, s := range existing {
|
||||
if err := h.ThumbnailGenerator.GenerateThumbnail(ctx, s, imageFile); err != nil {
|
||||
// just log if cover generation fails. We can try again on rescan
|
||||
logger.Errorf("Error generating thumbnail for %s: %v", imageFile.Path, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -202,7 +187,7 @@ func (h *ScanHandler) associateExisting(ctx context.Context, existing []*models.
|
||||
}
|
||||
|
||||
if !found {
|
||||
h.logInfo(ctx, "Adding %s to image %s", f.Path, i.DisplayName())
|
||||
logger.Infof("Adding %s to image %s", f.Path, i.DisplayName())
|
||||
|
||||
if err := h.CreatorUpdater.AddFileID(ctx, i.ID, f.ID); err != nil {
|
||||
return fmt.Errorf("adding file to image: %w", err)
|
||||
@@ -249,7 +234,7 @@ func (h *ScanHandler) getOrCreateFolderBasedGallery(ctx context.Context, f file.
|
||||
UpdatedAt: now,
|
||||
}
|
||||
|
||||
h.logInfo(ctx, "Creating folder-based gallery for %s", filepath.Dir(f.Base().Path))
|
||||
logger.Infof("Creating folder-based gallery for %s", filepath.Dir(f.Base().Path))
|
||||
|
||||
if err := h.GalleryFinder.Create(ctx, newGallery, nil); err != nil {
|
||||
return nil, fmt.Errorf("creating folder based gallery: %w", err)
|
||||
@@ -273,7 +258,7 @@ func (h *ScanHandler) associateFolderImages(ctx context.Context, g *models.Galle
|
||||
}
|
||||
|
||||
for _, ii := range i {
|
||||
h.logInfo(ctx, "Adding %s to gallery %s", ii.Path, g.Path)
|
||||
logger.Infof("Adding %s to gallery %s", ii.Path, g.Path)
|
||||
|
||||
if _, err := h.CreatorUpdater.UpdatePartial(ctx, ii.ID, models.ImagePartial{
|
||||
GalleryIDs: &models.UpdateIDs{
|
||||
@@ -307,7 +292,7 @@ func (h *ScanHandler) getOrCreateZipBasedGallery(ctx context.Context, zipFile fi
|
||||
UpdatedAt: now,
|
||||
}
|
||||
|
||||
h.logInfo(ctx, "%s doesn't exist. Creating new gallery...", zipFile.Base().Path)
|
||||
logger.Infof("%s doesn't exist. Creating new gallery...", zipFile.Base().Path)
|
||||
|
||||
if err := h.GalleryFinder.Create(ctx, newGallery, []file.ID{zipFile.Base().ID}); err != nil {
|
||||
return nil, fmt.Errorf("creating zip-based gallery: %w", err)
|
||||
@@ -345,7 +330,7 @@ func (h *ScanHandler) associateGallery(ctx context.Context, newImage *models.Ima
|
||||
if g != nil && !intslice.IntInclude(newImage.GalleryIDs.List(), g.ID) {
|
||||
ret = true
|
||||
newImage.GalleryIDs.Add(g.ID)
|
||||
h.logInfo(ctx, "Adding %s to gallery %s", f.Base().Path, g.Path)
|
||||
logger.Infof("Adding %s to gallery %s", f.Base().Path, g.Path)
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
|
||||
Reference in New Issue
Block a user