diff --git a/cmd/gonic/main.go b/cmd/gonic/main.go index ff606e7..2c9a4bf 100644 --- a/cmd/gonic/main.go +++ b/cmd/gonic/main.go @@ -2,14 +2,13 @@ package main import ( "flag" - "fmt" "log" "os" - "github.com/jinzhu/gorm" _ "github.com/jinzhu/gorm/dialects/sqlite" "github.com/peterbourgon/ff" + "github.com/sentriz/gonic/db" "github.com/sentriz/gonic/server" ) @@ -43,10 +42,7 @@ func main() { if _, err := os.Stat(*musicPath); os.IsNotExist(err) { log.Fatal("please provide a valid music directory") } - db, err := gorm.Open("sqlite3", fmt.Sprintf( - "%s?cache=shared&_busy_timeout=%d", - *dbPath, 2000, - )) + db, err := db.New(*dbPath) if err != nil { log.Fatalf("error opening database: %v\n", err) } diff --git a/cmd/gonicscan/main.go b/cmd/gonicscan/main.go index 429a954..5ac86e6 100644 --- a/cmd/gonicscan/main.go +++ b/cmd/gonicscan/main.go @@ -2,14 +2,13 @@ package main import ( "flag" - "fmt" "log" "os" - "github.com/jinzhu/gorm" _ "github.com/jinzhu/gorm/dialects/sqlite" "github.com/peterbourgon/ff" + "github.com/sentriz/gonic/db" "github.com/sentriz/gonic/scanner" ) @@ -29,14 +28,10 @@ func main() { if _, err := os.Stat(*musicPath); os.IsNotExist(err) { log.Fatal("please provide a valid music directory") } - db, err := gorm.Open("sqlite3", fmt.Sprintf( - "%s?cache=shared&_busy_timeout=%d", - *dbPath, 2000, - )) + db, err := db.New(*dbPath) if err != nil { log.Fatalf("error opening database: %v\n", err) } - db.SetLogger(log.New(os.Stdout, "gorm ", 0)) s := scanner.New( db, *musicPath, diff --git a/db/db.go b/db/db.go new file mode 100644 index 0000000..c5a9e90 --- /dev/null +++ b/db/db.go @@ -0,0 +1,34 @@ +package db + +import ( + "fmt" + "log" + "net/url" + "os" + + "github.com/jinzhu/gorm" + "github.com/pkg/errors" +) + +var ( + dbMaxOpenConns = 1 + dbOptions = url.Values{ + // with this, multiple connections share a single data and schema cache. + // see https://www.sqlite.org/sharedcache.html + "cache": []string{"shared"}, + // with this, the db sleeps for a little while when locked. can prevent + // a SQLITE_BUSY. see https://www.sqlite.org/c3ref/busy_timeout.html + "_busy_timeout": []string{"30000"}, + } +) + +func New(path string) (*gorm.DB, error) { + pathAndArgs := fmt.Sprintf("%s?%s", path, dbOptions.Encode()) + db, err := gorm.Open("sqlite3", pathAndArgs) + if err != nil { + return nil, errors.Wrap(err, "with gorm") + } + db.DB().SetMaxOpenConns(dbMaxOpenConns) + db.SetLogger(log.New(os.Stdout, "gorm ", 0)) + return db, nil +}