mirror of
https://github.com/navidrome/navidrome.git
synced 2026-10-08 02:17:25 +02:00
fix(plugins): skip the startup error reset when no plugin has an error (#6223)
The plugin manager clears last_error on every startup with an UPDATE that takes the SQLite write lock even when no row matches. On slow storage the startup scan often holds the lock at that moment, so the reset waited out the busy timeout and logged "database is locked", even with no plugins installed. ClearErrors now checks for errors with a read first and only writes when there is something to clear.
This commit is contained in:
parent
3f89baaec8
commit
336fa482f8
2 changed files with 23 additions and 0 deletions
|
|
@ -35,6 +35,14 @@ func (r *pluginRepository) ClearErrors() error {
|
|||
if !r.isPermitted() {
|
||||
return rest.ErrPermissionDenied
|
||||
}
|
||||
// An UPDATE takes the write lock even when nothing matches, so only run it when there is an error to clear
|
||||
var hasErrors bool
|
||||
if err := r.db.NewQuery("SELECT EXISTS (SELECT 1 FROM plugin WHERE last_error != '')").Row(&hasErrors); err != nil {
|
||||
return err
|
||||
}
|
||||
if !hasErrors {
|
||||
return nil
|
||||
}
|
||||
_, err := r.db.NewQuery("UPDATE plugin SET last_error = '' WHERE last_error != ''").Execute()
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
package persistence
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/deluan/rest"
|
||||
"github.com/navidrome/navidrome/db"
|
||||
"github.com/navidrome/navidrome/model"
|
||||
"github.com/navidrome/navidrome/model/request"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
|
|
@ -198,6 +201,18 @@ var _ = Describe("PluginRepository", func() {
|
|||
err := repo.ClearErrors()
|
||||
Expect(err).To(BeNil())
|
||||
})
|
||||
|
||||
It("does not need the write lock when no plugins have errors", func() {
|
||||
_ = repo.Put(&model.Plugin{ID: "clean-plugin", Path: "/plugins/c.wasm", Manifest: "{}", SHA256: "h1"})
|
||||
conn, err := db.Db().Conn(GinkgoT().Context())
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
DeferCleanup(conn.Close)
|
||||
_, err = conn.ExecContext(GinkgoT().Context(), "BEGIN IMMEDIATE")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
DeferCleanup(func() { _, _ = conn.ExecContext(context.Background(), "ROLLBACK") })
|
||||
|
||||
Expect(repo.ClearErrors()).To(Succeed())
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue