Files
wehub-resource-sync 1b8708893a
Security Scan / tests (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:12:26 +08:00

54 lines
1.5 KiB
Go

//go:build auth
package auth
import (
"net/url"
"strings"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
func openSQLiteDialector(path string) (gorm.Dialector, error) {
return sqlite.Open(buildSQLiteDSN(path)), nil
}
// buildSQLiteDSN augments a SQLite file path with connection pragmas that make
// the auth DB resilient on slow or contended storage.
//
// - _busy_timeout=5000 makes SQLite retry for up to 5s on SQLITE_BUSY instead
// of failing immediately. Network-backed storage (SMB/CIFS/NFS, e.g. Azure
// Files) is prone to transient lock contention during migration (see #10506).
// - _txlock=immediate takes the write lock at BEGIN, avoiding deadlocks when a
// read transaction later upgrades to a write during AutoMigrate.
//
// We deliberately do NOT set WAL journal mode: WAL relies on a shared-memory
// mmap that does not work over SMB/NFS, which is exactly the failing case here.
//
// Caller-supplied values for either pragma are preserved.
func buildSQLiteDSN(path string) string {
base := path
rawQuery := ""
if i := strings.IndexByte(path, '?'); i >= 0 {
base = path[:i]
rawQuery = path[i+1:]
}
values, err := url.ParseQuery(rawQuery)
if err != nil {
// An unparseable query string means a hand-crafted DSN we should not
// risk corrupting; leave it untouched.
return path
}
if values.Get("_busy_timeout") == "" {
values.Set("_busy_timeout", "5000")
}
if values.Get("_txlock") == "" {
values.Set("_txlock", "immediate")
}
return base + "?" + values.Encode()
}