Prevent SQLite busy errors
This commit is contained in:
@@ -54,6 +54,20 @@ func OpenSQLite(ctx context.Context, path string) (*Store, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// SQLite permits one writer at a time. Keep access serialized inside this
|
||||
// process and wait briefly for locks held during startup or maintenance.
|
||||
db.SetMaxOpenConns(1)
|
||||
db.SetMaxIdleConns(1)
|
||||
for _, stmt := range []string{
|
||||
`PRAGMA busy_timeout = 5000`,
|
||||
`PRAGMA journal_mode = WAL`,
|
||||
} {
|
||||
if _, err := db.ExecContext(ctx, stmt); err != nil {
|
||||
_ = db.Close()
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
s := &Store{db: db}
|
||||
if err := s.Migrate(ctx); err != nil {
|
||||
_ = db.Close()
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
_ "modernc.org/sqlite"
|
||||
@@ -63,3 +64,41 @@ VALUES ('rs_legacy', 'dev_legacy');
|
||||
t.Fatalf("got target %q, want ssh", sessions[0].Target)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSQLiteConcurrentAccessDoesNotReturnBusy(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
st, err := OpenSQLite(ctx, filepath.Join(t.TempDir(), "concurrent.db"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer st.Close()
|
||||
|
||||
enrolled, err := st.EnrollDevice(ctx, "router", "OpenWrt")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
errs := make(chan error, 80)
|
||||
for range 40 {
|
||||
wg.Add(2)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
_, _, err := st.ListRemoteSessions(ctx, enrolled.DeviceID, RemoteSessionListOptions{})
|
||||
errs <- err
|
||||
}()
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
_, err := st.SaveHeartbeat(ctx, enrolled.DeviceID, []byte(`{"hostname":"router"}`), []byte(`{}`))
|
||||
errs <- err
|
||||
}()
|
||||
}
|
||||
wg.Wait()
|
||||
close(errs)
|
||||
|
||||
for err := range errs {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user