+47
-1
internal/db/db.go
+47
-1
internal/db/db.go
···
8
8
"strings"
9
9
10
10
_ "github.com/mattn/go-sqlite3"
11
+
"yoten.app/internal/server/log"
11
12
)
12
13
13
14
type DB struct {
···
26
27
PrepareContext(ctx context.Context, query string) (*sql.Stmt, error)
27
28
}
28
29
29
-
func Make(ctx context.Context, dbPath string, logger *slog.Logger) (*DB, error) {
30
+
func Make(ctx context.Context, dbPath string) (*DB, error) {
30
31
opts := []string{
31
32
"_foreign_keys=1",
32
33
"_journal_mode=WAL",
33
34
"_synchronous=NORMAL",
34
35
"_auto_vacuum=incremental",
35
36
}
37
+
38
+
logger := log.FromContext(ctx)
39
+
logger = log.SubLogger(logger, "db")
36
40
37
41
db, err := sql.Open("sqlite3", dbPath+"?"+strings.Join(opts, "&"))
38
42
if err != nil {
···
236
240
logger,
237
241
}, nil
238
242
}
243
+
244
+
type migrationFn = func(*sql.Tx) error
245
+
246
+
func runMigration(c *sql.Conn, logger *slog.Logger, name string, migrationFn migrationFn) error {
247
+
logger = logger.With("migration", name)
248
+
249
+
tx, err := c.BeginTx(context.Background(), nil)
250
+
if err != nil {
251
+
return err
252
+
}
253
+
defer tx.Rollback()
254
+
255
+
var exists bool
256
+
err = tx.QueryRow("select exists (select 1 from migrations where name = ?)", name).Scan(&exists)
257
+
if err != nil {
258
+
return err
259
+
}
260
+
261
+
if !exists {
262
+
err = migrationFn(tx)
263
+
if err != nil {
264
+
logger.Error("failed to run migration", "err", err)
265
+
return err
266
+
}
267
+
268
+
_, err = tx.Exec("insert into migrations (name) values (?)", name)
269
+
if err != nil {
270
+
logger.Error("failed to mark migration as complete", "err", err)
271
+
return err
272
+
}
273
+
274
+
if err := tx.Commit(); err != nil {
275
+
return err
276
+
}
277
+
278
+
logger.Info("migration applied successfully")
279
+
} else {
280
+
logger.Warn("skipped migration, already applied")
281
+
}
282
+
283
+
return nil
284
+
}
+1
-1
internal/server/app.go
+1
-1
internal/server/app.go
···
51
51
func Make(ctx context.Context, config *config.Config) (*Server, error) {
52
52
logger := log.FromContext(ctx)
53
53
54
-
d, err := db.Make(ctx, config.Core.DbPath, log.SubLogger(logger, "db"))
54
+
d, err := db.Make(ctx, config.Core.DbPath)
55
55
if err != nil {
56
56
return nil, err
57
57
}