Create database package (refactoring)

This commit is contained in:
Frédéric Guillot 2018-08-01 20:28:45 -07:00
parent 17054b396e
commit cf03e0e338
30 changed files with 61 additions and 54 deletions

View File

@ -10,6 +10,7 @@ import (
"github.com/miniflux/miniflux/config" "github.com/miniflux/miniflux/config"
"github.com/miniflux/miniflux/daemon" "github.com/miniflux/miniflux/daemon"
"github.com/miniflux/miniflux/database"
"github.com/miniflux/miniflux/logger" "github.com/miniflux/miniflux/logger"
"github.com/miniflux/miniflux/storage" "github.com/miniflux/miniflux/storage"
"github.com/miniflux/miniflux/version" "github.com/miniflux/miniflux/version"
@ -33,10 +34,13 @@ func Parse() {
logger.EnableDebug() logger.EnableDebug()
} }
store := storage.NewStorage( db, err := database.NewConnectionPool(cfg.DatabaseURL(), cfg.DatabaseMinConns(), cfg.DatabaseMaxConns())
cfg.DatabaseURL(), if err != nil {
cfg.DatabaseMaxConnections(), logger.Fatal("Unable to connect to the database: %v", err)
) }
defer db.Close()
store := storage.NewStorage(db)
if *flagInfo { if *flagInfo {
info() info()
@ -49,7 +53,7 @@ func Parse() {
} }
if *flagMigrate { if *flagMigrate {
store.Migrate() database.Migrate(db)
return return
} }
@ -75,7 +79,7 @@ func Parse() {
// Run migrations and start the deamon. // Run migrations and start the deamon.
if cfg.RunMigrations() { if cfg.RunMigrations() {
store.Migrate() database.Migrate(db)
} }
// Create admin user and start the deamon. // Create admin user and start the deamon.

View File

@ -20,6 +20,7 @@ const (
defaultPollingFrequency = 60 defaultPollingFrequency = 60
defaultBatchSize = 10 defaultBatchSize = 10
defaultDatabaseMaxConns = 20 defaultDatabaseMaxConns = 20
defaultDatabaseMinConns = 1
defaultListenAddr = "127.0.0.1:8080" defaultListenAddr = "127.0.0.1:8080"
defaultCertFile = "" defaultCertFile = ""
defaultKeyFile = "" defaultKeyFile = ""
@ -119,11 +120,16 @@ func (c *Config) DatabaseURL() string {
return value return value
} }
// DatabaseMaxConnections returns the number of maximum database connections. // DatabaseMaxConns returns the maximum number of database connections.
func (c *Config) DatabaseMaxConnections() int { func (c *Config) DatabaseMaxConns() int {
return c.getInt("DATABASE_MAX_CONNS", defaultDatabaseMaxConns) return c.getInt("DATABASE_MAX_CONNS", defaultDatabaseMaxConns)
} }
// DatabaseMinConns returns the minimum number of database connections.
func (c *Config) DatabaseMinConns() int {
return c.getInt("DATABASE_MIN_CONNS", defaultDatabaseMinConns)
}
// ListenAddr returns the listen address for the HTTP server. // ListenAddr returns the listen address for the HTTP server.
func (c *Config) ListenAddr() string { func (c *Config) ListenAddr() string {
if port := os.Getenv("PORT"); port != "" { if port := os.Getenv("PORT"); port != "" {

View File

@ -59,6 +59,5 @@ func Run(cfg *config.Config, store *storage.Storage) {
defer cancel() defer cancel()
server.Shutdown(ctx) server.Shutdown(ctx)
store.Close()
logger.Info("Server gracefully stopped") logger.Info("Server gracefully stopped")
} }

25
database/database.go Normal file
View File

@ -0,0 +1,25 @@
// Copyright 2018 Frédéric Guillot. All rights reserved.
// Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file.
package database
import (
"database/sql"
// Postgresql driver import
_ "github.com/lib/pq"
)
// NewConnectionPool configures the database connection pool.
func NewConnectionPool(dsn string, minConnections, maxConnections int) (*sql.DB, error) {
db, err := sql.Open("postgres", dsn)
if err != nil {
return nil, err
}
db.SetMaxOpenConns(maxConnections)
db.SetMaxIdleConns(minConnections)
return db, nil
}

View File

@ -1,23 +1,23 @@
// Copyright 2017 Frédéric Guillot. All rights reserved. // Copyright 2018 Frédéric Guillot. All rights reserved.
// Use of this source code is governed by the Apache 2.0 // Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package storage package database
import ( import (
"database/sql"
"fmt" "fmt"
"strconv" "strconv"
"github.com/miniflux/miniflux/logger" "github.com/miniflux/miniflux/logger"
"github.com/miniflux/miniflux/sql"
) )
const schemaVersion = 20 const schemaVersion = 20
// Migrate run database migrations. // Migrate executes database migrations.
func (s *Storage) Migrate() { func Migrate(db *sql.DB) {
var currentVersion int var currentVersion int
s.db.QueryRow(`select version from schema_version`).Scan(&currentVersion) db.QueryRow(`select version from schema_version`).Scan(&currentVersion)
fmt.Println("Current schema version:", currentVersion) fmt.Println("Current schema version:", currentVersion)
fmt.Println("Latest schema version:", schemaVersion) fmt.Println("Latest schema version:", schemaVersion)
@ -25,31 +25,31 @@ func (s *Storage) Migrate() {
for version := currentVersion + 1; version <= schemaVersion; version++ { for version := currentVersion + 1; version <= schemaVersion; version++ {
fmt.Println("Migrating to version:", version) fmt.Println("Migrating to version:", version)
tx, err := s.db.Begin() tx, err := db.Begin()
if err != nil { if err != nil {
logger.Fatal("[Storage:Migrate] %v", err) logger.Fatal("[Migrate] %v", err)
} }
rawSQL := sql.SqlMap["schema_version_"+strconv.Itoa(version)] rawSQL := SqlMap["schema_version_"+strconv.Itoa(version)]
// fmt.Println(rawSQL) // fmt.Println(rawSQL)
_, err = tx.Exec(rawSQL) _, err = tx.Exec(rawSQL)
if err != nil { if err != nil {
tx.Rollback() tx.Rollback()
logger.Fatal("[Storage:Migrate] %v", err) logger.Fatal("[Migrate] %v", err)
} }
if _, err := tx.Exec(`delete from schema_version`); err != nil { if _, err := tx.Exec(`delete from schema_version`); err != nil {
tx.Rollback() tx.Rollback()
logger.Fatal("[Storage:Migrate] %v", err) logger.Fatal("[Migrate] %v", err)
} }
if _, err := tx.Exec(`insert into schema_version (version) values($1)`, version); err != nil { if _, err := tx.Exec(`insert into schema_version (version) values($1)`, version); err != nil {
tx.Rollback() tx.Rollback()
logger.Fatal("[Storage:Migrate] %v", err) logger.Fatal("[Migrate] %v", err)
} }
if err := tx.Commit(); err != nil { if err := tx.Commit(); err != nil {
logger.Fatal("[Storage:Migrate] %v", err) logger.Fatal("[Migrate] %v", err)
} }
} }
} }

View File

@ -1,6 +1,6 @@
// Code generated by go generate; DO NOT EDIT. // Code generated by go generate; DO NOT EDIT.
package sql package database
var SqlMap = map[string]string{ var SqlMap = map[string]string{
"schema_version_1": `create table schema_version ( "schema_version_1": `create table schema_version (

View File

@ -209,7 +209,7 @@ func main() {
generateBinaryBundle("ui/static/bin.go", glob("ui/static/bin/*")) generateBinaryBundle("ui/static/bin.go", glob("ui/static/bin/*"))
generateBundle("sql/sql.go", "sql", "SqlMap", glob("sql/*.sql")) generateBundle("database/sql.go", "database", "SqlMap", glob("database/sql/*.sql"))
generateBundle("template/views.go", "template", "templateViewsMap", glob("template/html/*.html")) generateBundle("template/views.go", "template", "templateViewsMap", glob("template/html/*.html"))
generateBundle("template/common.go", "template", "templateCommonMap", glob("template/html/common/*.html")) generateBundle("template/common.go", "template", "templateCommonMap", glob("template/html/common/*.html"))
generateBundle("locale/translations.go", "locale", "translations", glob("locale/translations/*.json")) generateBundle("locale/translations.go", "locale", "translations", glob("locale/translations/*.json"))

View File

@ -5,7 +5,7 @@
package main package main
//go:generate go run generate.go //go:generate go run generate.go
//go:generate gofmt -s -w sql/sql.go //go:generate gofmt -s -w database/sql.go
//go:generate gofmt -s -w ui/static/css.go //go:generate gofmt -s -w ui/static/css.go
//go:generate gofmt -s -w ui/static/bin.go //go:generate gofmt -s -w ui/static/bin.go
//go:generate gofmt -s -w ui/static/js.go //go:generate gofmt -s -w ui/static/js.go

View File

@ -1,10 +0,0 @@
// Copyright 2018 Frédéric Guillot. All rights reserved.
// Use of this source code is governed by the MIT license
// that can be found in the LICENSE file.
/*
Package sql contains all SQL queries or database schema instructions.
*/
package sql

View File

@ -6,10 +6,6 @@ package storage
import ( import (
"database/sql" "database/sql"
// Postgresql driver import
_ "github.com/lib/pq"
"github.com/miniflux/miniflux/logger"
) )
// Storage handles all operations related to the database. // Storage handles all operations related to the database.
@ -17,20 +13,7 @@ type Storage struct {
db *sql.DB db *sql.DB
} }
// Close closes all database connections.
func (s *Storage) Close() {
s.db.Close()
}
// NewStorage returns a new Storage. // NewStorage returns a new Storage.
func NewStorage(databaseURL string, maxOpenConns int) *Storage { func NewStorage(db *sql.DB) *Storage {
db, err := sql.Open("postgres", databaseURL) return &Storage{db}
if err != nil {
logger.Fatal("[Storage] Unable to connect to the database: %v", err)
}
db.SetMaxOpenConns(maxOpenConns)
db.SetMaxIdleConns(2)
return &Storage{db: db}
} }