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:
WithoutPants
2022-11-21 06:49:10 +11:00
committed by GitHub
parent 420c6fa9d7
commit f39fa416a9
54 changed files with 626 additions and 311 deletions

View File

@@ -95,7 +95,7 @@ func (s autotagScraper) viaScene(ctx context.Context, _client *http.Client, scen
const trimExt = false
// populate performers, studio and tags based on scene path
if err := txn.WithTxn(ctx, s.txnManager, func(ctx context.Context) error {
if err := txn.WithReadTxn(ctx, s.txnManager, func(ctx context.Context) error {
path := scene.Path
if path == "" {
return nil
@@ -144,7 +144,7 @@ func (s autotagScraper) viaGallery(ctx context.Context, _client *http.Client, ga
var ret *ScrapedGallery
// populate performers, studio and tags based on scene path
if err := txn.WithTxn(ctx, s.txnManager, func(ctx context.Context) error {
if err := txn.WithReadTxn(ctx, s.txnManager, func(ctx context.Context) error {
path := gallery.Path
performers, err := autotagMatchPerformers(ctx, path, s.performerReader, trimExt)
if err != nil {

View File

@@ -350,7 +350,7 @@ func (c Cache) ScrapeID(ctx context.Context, scraperID string, id int, ty Scrape
func (c Cache) getScene(ctx context.Context, sceneID int) (*models.Scene, error) {
var ret *models.Scene
if err := txn.WithTxn(ctx, c.txnManager, func(ctx context.Context) error {
if err := txn.WithReadTxn(ctx, c.txnManager, func(ctx context.Context) error {
var err error
ret, err = c.repository.SceneFinder.Find(ctx, sceneID)
return err
@@ -362,7 +362,7 @@ func (c Cache) getScene(ctx context.Context, sceneID int) (*models.Scene, error)
func (c Cache) getGallery(ctx context.Context, galleryID int) (*models.Gallery, error) {
var ret *models.Gallery
if err := txn.WithTxn(ctx, c.txnManager, func(ctx context.Context) error {
if err := txn.WithReadTxn(ctx, c.txnManager, func(ctx context.Context) error {
var err error
ret, err = c.repository.GalleryFinder.Find(ctx, galleryID)

View File

@@ -47,7 +47,7 @@ func (c Cache) postScrape(ctx context.Context, content ScrapedContent) (ScrapedC
}
func (c Cache) postScrapePerformer(ctx context.Context, p models.ScrapedPerformer) (ScrapedContent, error) {
if err := txn.WithTxn(ctx, c.txnManager, func(ctx context.Context) error {
if err := txn.WithReadTxn(ctx, c.txnManager, func(ctx context.Context) error {
tqb := c.repository.TagFinder
tags, err := postProcessTags(ctx, tqb, p.Tags)
@@ -73,7 +73,7 @@ func (c Cache) postScrapePerformer(ctx context.Context, p models.ScrapedPerforme
func (c Cache) postScrapeMovie(ctx context.Context, m models.ScrapedMovie) (ScrapedContent, error) {
if m.Studio != nil {
if err := txn.WithTxn(ctx, c.txnManager, func(ctx context.Context) error {
if err := txn.WithReadTxn(ctx, c.txnManager, func(ctx context.Context) error {
return match.ScrapedStudio(ctx, c.repository.StudioFinder, m.Studio, nil)
}); err != nil {
return nil, err
@@ -106,7 +106,7 @@ func (c Cache) postScrapeScenePerformer(ctx context.Context, p models.ScrapedPer
}
func (c Cache) postScrapeScene(ctx context.Context, scene ScrapedScene) (ScrapedContent, error) {
if err := txn.WithTxn(ctx, c.txnManager, func(ctx context.Context) error {
if err := txn.WithReadTxn(ctx, c.txnManager, func(ctx context.Context) error {
pqb := c.repository.PerformerFinder
mqb := c.repository.MovieFinder
tqb := c.repository.TagFinder
@@ -160,7 +160,7 @@ func (c Cache) postScrapeScene(ctx context.Context, scene ScrapedScene) (Scraped
}
func (c Cache) postScrapeGallery(ctx context.Context, g ScrapedGallery) (ScrapedContent, error) {
if err := txn.WithTxn(ctx, c.txnManager, func(ctx context.Context) error {
if err := txn.WithReadTxn(ctx, c.txnManager, func(ctx context.Context) error {
pqb := c.repository.PerformerFinder
tqb := c.repository.TagFinder
sqb := c.repository.StudioFinder

View File

@@ -131,7 +131,7 @@ func (c Client) FindStashBoxSceneByFingerprints(ctx context.Context, sceneID int
func (c Client) FindStashBoxScenesByFingerprints(ctx context.Context, ids []int) ([][]*scraper.ScrapedScene, error) {
var fingerprints [][]*graphql.FingerprintQueryInput
if err := txn.WithTxn(ctx, c.txnManager, func(ctx context.Context) error {
if err := txn.WithReadTxn(ctx, c.txnManager, func(ctx context.Context) error {
qb := c.repository.Scene
for _, sceneID := range ids {
@@ -245,7 +245,7 @@ func (c Client) SubmitStashBoxFingerprints(ctx context.Context, sceneIDs []strin
var fingerprints []graphql.FingerprintSubmission
if err := txn.WithTxn(ctx, c.txnManager, func(ctx context.Context) error {
if err := txn.WithReadTxn(ctx, c.txnManager, func(ctx context.Context) error {
qb := c.repository.Scene
for _, sceneID := range ids {
@@ -386,7 +386,7 @@ func (c Client) FindStashBoxPerformersByNames(ctx context.Context, performerIDs
var performers []*models.Performer
if err := txn.WithTxn(ctx, c.txnManager, func(ctx context.Context) error {
if err := txn.WithReadTxn(ctx, c.txnManager, func(ctx context.Context) error {
qb := c.repository.Performer
for _, performerID := range ids {
@@ -420,7 +420,7 @@ func (c Client) FindStashBoxPerformersByPerformerNames(ctx context.Context, perf
var performers []*models.Performer
if err := txn.WithTxn(ctx, c.txnManager, func(ctx context.Context) error {
if err := txn.WithReadTxn(ctx, c.txnManager, func(ctx context.Context) error {
qb := c.repository.Performer
for _, performerID := range ids {
@@ -705,7 +705,7 @@ func (c Client) sceneFragmentToScrapedScene(ctx context.Context, s *graphql.Scen
ss.Image = getFirstImage(ctx, c.getHTTPClient(), s.Images)
}
if err := txn.WithTxn(ctx, c.txnManager, func(ctx context.Context) error {
if err := txn.WithReadTxn(ctx, c.txnManager, func(ctx context.Context) error {
pqb := c.repository.Performer
tqb := c.repository.Tag