Skip to content

Commit

Permalink
Rename sql.Database to sql.Helper
Browse files Browse the repository at this point in the history
Also, DB -> SQLHelperInjector, Routes -> HTTPRouterInjector.
  • Loading branch information
markuswustenberg committed Sep 12, 2024
1 parent bf4670c commit b4f6dee
Show file tree
Hide file tree
Showing 8 changed files with 110 additions and 103 deletions.
4 changes: 2 additions & 2 deletions http/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ func (s *Server) setupRoutes() {
r.Use(s.sm.LoadAndSave)
r.Use(httph.NoClickjacking)

if s.setupUserRoutes != nil {
s.setupUserRoutes(r)
if s.httpRouterInjector != nil {
s.httpRouterInjector(r)
}
})
})
Expand Down
44 changes: 21 additions & 23 deletions http/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,22 @@ import (
)

type Server struct {
adminPassword string
baseURL string
db *sql.Database
log *snorkel.Logger
mux *chi.Mux
server *http.Server
setupUserRoutes func(chi.Router)
sm *scs.SessionManager
adminPassword string
baseURL string
log *snorkel.Logger
mux *chi.Mux
server *http.Server
httpRouterInjector func(chi.Router)
sm *scs.SessionManager
}

type NewServerOptions struct {
AdminPassword string
BaseURL string
DB *sql.Database
Log *snorkel.Logger
Routes func(chi.Router)
SecureCookie bool
AdminPassword string
BaseURL string
HTTPRouterInjector func(chi.Router)
Log *snorkel.Logger
SecureCookie bool
SQLHelper *sql.Helper
}

func NewServer(opts NewServerOptions) *Server {
Expand All @@ -44,16 +43,16 @@ func NewServer(opts NewServerOptions) *Server {
mux := chi.NewMux()

sm := scs.New()
sm.Store = sqlite3store.New(opts.DB.DB.DB)
sm.Store = sqlite3store.New(opts.SQLHelper.DB.DB)
sm.Lifetime = 365 * 24 * time.Hour
sm.Cookie.Secure = opts.SecureCookie

return &Server{
adminPassword: opts.AdminPassword,
baseURL: strings.TrimSuffix(opts.BaseURL, "/"),
db: opts.DB,
log: opts.Log,
mux: mux,
adminPassword: opts.AdminPassword,
baseURL: strings.TrimSuffix(opts.BaseURL, "/"),
httpRouterInjector: opts.HTTPRouterInjector,
log: opts.Log,
mux: mux,
server: &http.Server{
Addr: ":8080",
Handler: mux,
Expand All @@ -62,13 +61,12 @@ func NewServer(opts NewServerOptions) *Server {
WriteTimeout: 5 * time.Second,
IdleTimeout: 5 * time.Second,
},
setupUserRoutes: opts.Routes,
sm: sm,
sm: sm,
}
}

func (s *Server) Start() error {
s.log.Event("Starting http server", 1)
s.log.Event("Starting http server", 1, "url", s.baseURL)

s.setupRoutes()

Expand Down
14 changes: 7 additions & 7 deletions http/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,20 @@ import (

func TestServer_Start(t *testing.T) {
t.Run("can start and stop server", func(t *testing.T) {
db := sqltest.CreateDatabase(t)
sqlHelper := sqltest.NewHelper(t)

routes := func(r chi.Router) {
httpRouterInjector := func(r chi.Router) {
r.Get("/", func(w http2.ResponseWriter, r *http2.Request) {
_, _ = w.Write([]byte("OK"))
})
}

s := http.NewServer(http.NewServerOptions{
AdminPassword: "correct horse battery staple",
BaseURL: "http://localhost:8080",
DB: db,
SecureCookie: false,
Routes: routes,
AdminPassword: "correct horse battery staple",
BaseURL: "http://localhost:8080",
HTTPRouterInjector: httpRouterInjector,
SecureCookie: false,
SQLHelper: sqlHelper,
})

go s.Start()
Expand Down
36 changes: 22 additions & 14 deletions service/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ import (
)

type Options struct {
Log *snorkel.Logger
Migrate bool
Routes func(chi.Router)
HTTPRouterInjector func(chi.Router)
Log *snorkel.Logger
Migrate bool
SQLHelperInjector func(*sql.Helper)
}

func Start(opts Options) {
Expand Down Expand Up @@ -47,16 +48,19 @@ func start(opts Options) error {
ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGTERM, syscall.SIGINT)
defer stop()

db := sql.NewDatabase(sql.NewDatabaseOptions{
sqlHelper := sql.NewHelper(sql.NewHelperOptions{
Log: log,
Path: env.GetStringOrDefault("DATABASE_PATH", "app.db"),
})
if err := db.Connect(); err != nil {
if err := sqlHelper.Connect(); err != nil {
return err
}
if opts.SQLHelperInjector != nil {
opts.SQLHelperInjector(sqlHelper)
}

q := goqite.New(goqite.NewOpts{
DB: db.DB.DB,
DB: sqlHelper.DB.DB,
Name: "jobs",
})

Expand All @@ -65,15 +69,15 @@ func start(opts Options) error {
Queue: q,
})

db.SetJobsQueue(q)
sqlHelper.SetJobsQueue(q)

s := http.NewServer(http.NewServerOptions{
AdminPassword: env.GetStringOrDefault("ADMIN_PASSWORD", "correct horse battery staple"),
BaseURL: env.GetStringOrDefault("BASE_URL", "http://localhost:8080"),
DB: db,
Log: log,
Routes: opts.Routes,
SecureCookie: env.GetBoolOrDefault("SECURE_COOKIE", true),
AdminPassword: env.GetStringOrDefault("ADMIN_PASSWORD", "correct horse battery staple"),
BaseURL: env.GetStringOrDefault("BASE_URL", "http://localhost:8080"),
HTTPRouterInjector: opts.HTTPRouterInjector,
Log: log,
SecureCookie: env.GetBoolOrDefault("SECURE_COOKIE", true),
SQLHelper: sqlHelper,
})

eg, ctx := errgroup.WithContext(ctx)
Expand Down Expand Up @@ -110,7 +114,7 @@ func migrate(opts Options) error {

_ = env.Load()

db := sql.NewDatabase(sql.NewDatabaseOptions{
db := sql.NewHelper(sql.NewHelperOptions{
Log: log,
Path: env.GetStringOrDefault("DATABASE_PATH", "app.db"),
})
Expand All @@ -134,3 +138,7 @@ type logAdapter struct {
func (l *logAdapter) Info(msg string, args ...any) {
l.log.Event(msg, 1, args...)
}

func NewLogger() *snorkel.Logger {
return snorkel.New(snorkel.Options{})
}
43 changes: 22 additions & 21 deletions sql/database.go → sql/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,22 @@ import (
"maragu.dev/snorkel"
)

type Database struct {
type Helper struct {
DB *sqlx.DB
jobsQueue *goqite.Queue
log *snorkel.Logger
path string
}

type NewDatabaseOptions struct {
Log *snorkel.Logger
Path string
type NewHelperOptions struct {
HelperInjector func(*Helper)
Log *snorkel.Logger
Path string
}

// NewDatabase with the given options.
// NewHelper with the given options.
// If no logger is provided, logs are discarded.
func NewDatabase(opts NewDatabaseOptions) *Database {
func NewHelper(opts NewHelperOptions) *Helper {
if opts.Log == nil {
opts.Log = snorkel.New(snorkel.Options{W: io.Discard})
}
Expand All @@ -40,20 +41,20 @@ func NewDatabase(opts NewDatabaseOptions) *Database {
// - Enable foreign key checks
opts.Path += "?_journal=WAL&_timeout=5000&_fk=true"

return &Database{
return &Helper{
log: opts.Log,
path: opts.Path,
}
}

func (d *Database) Connect() error {
func (h *Helper) Connect() error {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

d.log.Event("Starting database", 1, "path", d.path)
h.log.Event("Starting database", 1, "path", h.path)

var err error
d.DB, err = sqlx.ConnectContext(ctx, "sqlite3", d.path)
h.DB, err = sqlx.ConnectContext(ctx, "sqlite3", h.path)
if err != nil {
return err
}
Expand All @@ -62,8 +63,8 @@ func (d *Database) Connect() error {
}

// InTransaction runs callback in a transaction, and makes sure to handle rollbacks, commits etc.
func (d *Database) InTransaction(ctx context.Context, callback func(tx *sqlx.Tx) error) (err error) {
tx, err := d.DB.BeginTxx(ctx, &sql.TxOptions{Isolation: sql.LevelSerializable})
func (h *Helper) InTransaction(ctx context.Context, callback func(tx *sqlx.Tx) error) (err error) {
tx, err := h.DB.BeginTxx(ctx, &sql.TxOptions{Isolation: sql.LevelSerializable})
if err != nil {
return errors.Wrap(err, "error beginning transaction")
}
Expand All @@ -90,16 +91,16 @@ func rollback(tx *sqlx.Tx, err error) error {
return err
}

func (d *Database) MigrateUp(ctx context.Context) error {
func (h *Helper) MigrateUp(ctx context.Context) error {
// TODO some migrations should be in goo
return migrate.Up(ctx, d.DB.DB, d.getMigrations())
return migrate.Up(ctx, h.DB.DB, h.getMigrations())
}

func (d *Database) MigrateDown(ctx context.Context) error {
return migrate.Down(ctx, d.DB.DB, d.getMigrations())
func (h *Helper) MigrateDown(ctx context.Context) error {
return migrate.Down(ctx, h.DB.DB, h.getMigrations())
}

func (d *Database) getMigrations() fs.FS {
func (h *Helper) getMigrations() fs.FS {
for _, path := range []string{"sql/migrations", "../sql/migrations"} {
migrations := os.DirFS(path)

Expand All @@ -112,13 +113,13 @@ func (d *Database) getMigrations() fs.FS {
panic("no migrations found")
}

func (d *Database) Ping(ctx context.Context) error {
return d.InTransaction(ctx, func(tx *sqlx.Tx) error {
func (h *Helper) Ping(ctx context.Context) error {
return h.InTransaction(ctx, func(tx *sqlx.Tx) error {
_, err := tx.ExecContext(ctx, `select 1`)
return err
})
}

func (d *Database) SetJobsQueue(q *goqite.Queue) {
d.jobsQueue = q
func (h *Helper) SetJobsQueue(q *goqite.Queue) {
h.jobsQueue = q
}
4 changes: 2 additions & 2 deletions sql/database_test.go → sql/helper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import (
"maragu.dev/goo/sqltest"
)

func TestDatabase_Migrate(t *testing.T) {
func TestHelper_Migrate(t *testing.T) {
t.Run("can migrate down and back up", func(t *testing.T) {
db := sqltest.CreateDatabase(t)
db := sqltest.NewHelper(t)

err := db.MigrateDown(context.Background())
is.NotError(t, err)
Expand Down
34 changes: 0 additions & 34 deletions sqltest/database.go

This file was deleted.

34 changes: 34 additions & 0 deletions sqltest/helper.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package sqltest

import (
"context"
"testing"

"github.com/maragudk/goqite"

"maragu.dev/goo/sql"
)

// NewHelper for testing.
func NewHelper(t *testing.T) *sql.Helper {
t.Helper()

sqlHelper := sql.NewHelper(sql.NewHelperOptions{
Path: ":memory:",
})
if err := sqlHelper.Connect(); err != nil {
t.Fatal(err)
}

if err := sqlHelper.MigrateUp(context.Background()); err != nil {
t.Fatal(err)
}

q := goqite.New(goqite.NewOpts{
DB: sqlHelper.DB.DB,
Name: "jobs",
})
sqlHelper.SetJobsQueue(q)

return sqlHelper
}

0 comments on commit b4f6dee

Please sign in to comment.