mirror of
https://github.com/navidrome/navidrome.git
synced 2025-04-24 15:40:56 +03:00
fix(server): encapsulated way to upgrade tx to write mode
Signed-off-by: Deluan <deluan@navidrome.org>
This commit is contained in:
parent
b6cc32a436
commit
a5741050df
@ -42,5 +42,6 @@ type DataStore interface {
|
||||
Resource(ctx context.Context, model interface{}) ResourceRepository
|
||||
|
||||
WithTx(block func(tx DataStore) error, scope ...string) error
|
||||
WithTxImmediate(block func(tx DataStore) error, scope ...string) error
|
||||
GC(ctx context.Context) error
|
||||
}
|
||||
|
@ -143,6 +143,20 @@ func (s *SQLStore) WithTx(block func(tx model.DataStore) error, scope ...string)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *SQLStore) WithTxImmediate(block func(tx model.DataStore) error, scope ...string) error {
|
||||
ctx := context.Background()
|
||||
return s.WithTx(func(tx model.DataStore) error {
|
||||
// Workaround to force the transaction to be upgraded to immediate mode to avoid deadlocks
|
||||
// See https://berthub.eu/articles/posts/a-brief-post-on-sqlite3-database-locked-despite-timeout/
|
||||
_ = tx.Property(ctx).Put("tmp_lock_flag", "")
|
||||
defer func() {
|
||||
_ = tx.Property(ctx).Delete("tmp_lock_flag")
|
||||
}()
|
||||
|
||||
return block(tx)
|
||||
}, scope...)
|
||||
}
|
||||
|
||||
func (s *SQLStore) GC(ctx context.Context) error {
|
||||
trace := func(ctx context.Context, msg string, f func() error) func() error {
|
||||
return func() error {
|
||||
|
@ -6,7 +6,6 @@ import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/navidrome/navidrome/core/scrobbler"
|
||||
"github.com/navidrome/navidrome/log"
|
||||
"github.com/navidrome/navidrome/model"
|
||||
@ -113,15 +112,7 @@ func (api *Router) setStar(ctx context.Context, star bool, ids ...string) error
|
||||
return nil
|
||||
}
|
||||
event := &events.RefreshResource{}
|
||||
err := api.ds.WithTx(func(tx model.DataStore) error {
|
||||
// Workaround to force the transaction to be upgraded to immediate mode to avoid deadlocks
|
||||
// See https://berthub.eu/articles/posts/a-brief-post-on-sqlite3-database-locked-despite-timeout/
|
||||
tmpID := uuid.NewString()
|
||||
_ = tx.Property(ctx).Put("tmp_"+tmpID, "")
|
||||
defer func() {
|
||||
_ = tx.Property(ctx).Delete("tmp_" + tmpID)
|
||||
}()
|
||||
|
||||
err := api.ds.WithTxImmediate(func(tx model.DataStore) error {
|
||||
for _, id := range ids {
|
||||
exist, err := tx.Album(ctx).Exists(id)
|
||||
if err != nil {
|
||||
|
@ -213,6 +213,10 @@ func (db *MockDataStore) WithTx(block func(tx model.DataStore) error, label ...s
|
||||
return block(db)
|
||||
}
|
||||
|
||||
func (db *MockDataStore) WithTxImmediate(block func(tx model.DataStore) error, label ...string) error {
|
||||
return block(db)
|
||||
}
|
||||
|
||||
func (db *MockDataStore) Resource(context.Context, any) model.ResourceRepository {
|
||||
return struct{ model.ResourceRepository }{}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user