fix: use transaction for MBID updates to prevent SQLite deadlock
updateMBIDs was calling l.db.ExecContext (main connection) while inside a transaction that held the write lock. With SQLite's SetMaxOpenConns(1), this deadlocked — the UPDATE waited for the transaction to release the lock, but the transaction waited for the UPDATE to complete. Fix: pass *sql.Tx through processMetadata to updateMBIDs and use tx.ExecContext instead. All MBID writes now happen within the same transaction as the entity upserts.
This commit is contained in:
@@ -973,7 +973,7 @@ func (l *Library) saveAudioFile(
|
|||||||
|
|
||||||
// Process metadata and create related records.
|
// Process metadata and create related records.
|
||||||
recordingID, err := l.processMetadata(
|
recordingID, err := l.processMetadata(
|
||||||
q, cache, metrics, result, thumbChan,
|
q, tx, cache, metrics, result, thumbChan,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("could not process metadata: %w", err)
|
return fmt.Errorf("could not process metadata: %w", err)
|
||||||
@@ -1067,7 +1067,7 @@ func (l *Library) updateAudioFileMetadata(
|
|||||||
|
|
||||||
// Process metadata and create related records.
|
// Process metadata and create related records.
|
||||||
recordingID, err := l.processMetadata(
|
recordingID, err := l.processMetadata(
|
||||||
q, cache, metrics, result, thumbChan,
|
q, tx, cache, metrics, result, thumbChan,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("could not process metadata: %w", err)
|
return fmt.Errorf("could not process metadata: %w", err)
|
||||||
@@ -1148,6 +1148,7 @@ func (l *Library) updateAudioFileMetadata(
|
|||||||
// asynchronously.
|
// asynchronously.
|
||||||
func (l *Library) processMetadata(
|
func (l *Library) processMetadata(
|
||||||
q *sqlcgen.Queries,
|
q *sqlcgen.Queries,
|
||||||
|
tx *sql.Tx,
|
||||||
cache *entityCache,
|
cache *entityCache,
|
||||||
metrics *ScanMetrics,
|
metrics *ScanMetrics,
|
||||||
result importResult,
|
result importResult,
|
||||||
@@ -1236,9 +1237,9 @@ func (l *Library) processMetadata(
|
|||||||
|
|
||||||
// 7. Update MusicBrainz IDs (if present in tags).
|
// 7. Update MusicBrainz IDs (if present in tags).
|
||||||
if releaseGroupID.Valid {
|
if releaseGroupID.Valid {
|
||||||
l.updateMBIDs(cache, tags, artistName, releaseGroupID.Int64, recording.ID)
|
l.updateMBIDs(tx, cache, tags, artistName, releaseGroupID.Int64, recording.ID)
|
||||||
} else {
|
} else {
|
||||||
l.updateMBIDs(cache, tags, artistName, 0, recording.ID)
|
l.updateMBIDs(tx, cache, tags, artistName, 0, recording.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
return recording.ID, nil
|
return recording.ID, nil
|
||||||
@@ -1249,6 +1250,7 @@ func (l *Library) processMetadata(
|
|||||||
// queries predate the mbid columns. Skips silently if tags have
|
// queries predate the mbid columns. Skips silently if tags have
|
||||||
// no MBIDs.
|
// no MBIDs.
|
||||||
func (l *Library) updateMBIDs(
|
func (l *Library) updateMBIDs(
|
||||||
|
tx *sql.Tx,
|
||||||
cache *entityCache,
|
cache *entityCache,
|
||||||
tags *metadata.TrackMetadata,
|
tags *metadata.TrackMetadata,
|
||||||
artistName string,
|
artistName string,
|
||||||
@@ -1263,7 +1265,7 @@ func (l *Library) updateMBIDs(
|
|||||||
|
|
||||||
if artistMBID != "" {
|
if artistMBID != "" {
|
||||||
if artist, ok := cache.artists[artistName]; ok {
|
if artist, ok := cache.artists[artistName]; ok {
|
||||||
_, _ = l.db.ExecContext(
|
_, _ = tx.ExecContext(l.ctx,
|
||||||
"UPDATE artists SET mbid = ? WHERE id = ? AND (mbid IS NULL OR mbid = '')",
|
"UPDATE artists SET mbid = ? WHERE id = ? AND (mbid IS NULL OR mbid = '')",
|
||||||
artistMBID, artist.ID,
|
artistMBID, artist.ID,
|
||||||
)
|
)
|
||||||
@@ -1272,7 +1274,7 @@ func (l *Library) updateMBIDs(
|
|||||||
|
|
||||||
// Release group MBID.
|
// Release group MBID.
|
||||||
if tags.ReleaseGroupMBID != "" && releaseGroupID > 0 {
|
if tags.ReleaseGroupMBID != "" && releaseGroupID > 0 {
|
||||||
_, _ = l.db.ExecContext(
|
_, _ = tx.ExecContext(l.ctx,
|
||||||
"UPDATE release_groups SET mbid = ? WHERE id = ? AND (mbid IS NULL OR mbid = '')",
|
"UPDATE release_groups SET mbid = ? WHERE id = ? AND (mbid IS NULL OR mbid = '')",
|
||||||
tags.ReleaseGroupMBID, releaseGroupID,
|
tags.ReleaseGroupMBID, releaseGroupID,
|
||||||
)
|
)
|
||||||
@@ -1280,7 +1282,7 @@ func (l *Library) updateMBIDs(
|
|||||||
|
|
||||||
// Recording MBID.
|
// Recording MBID.
|
||||||
if tags.RecordingMBID != "" && recordingID > 0 {
|
if tags.RecordingMBID != "" && recordingID > 0 {
|
||||||
_, _ = l.db.ExecContext(
|
_, _ = tx.ExecContext(l.ctx,
|
||||||
"UPDATE recordings SET mbid = ? WHERE id = ? AND (mbid IS NULL OR mbid = '')",
|
"UPDATE recordings SET mbid = ? WHERE id = ? AND (mbid IS NULL OR mbid = '')",
|
||||||
tags.RecordingMBID, recordingID,
|
tags.RecordingMBID, recordingID,
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user