diff --git a/appview/db/db.go b/appview/db/db.go --- a/appview/db/db.go +++ b/appview/db/db.go @@ -27,19 +27,28 @@ } func Make(dbPath string) (*DB, error) { - db, err := sql.Open("sqlite3", dbPath+"?_foreign_keys=1") + // https://github.com/mattn/go-sqlite3#connection-string + opts := []string{ + "_foreign_keys=1", + "_journal_mode=WAL", + "_synchronous=NORMAL", + "_auto_vacuum=incremental", + } + + db, err := sql.Open("sqlite3", dbPath+"?"+strings.Join(opts, "&")) if err != nil { return nil, err } - _, err = db.Exec(` - pragma journal_mode = WAL; - pragma synchronous = normal; - pragma temp_store = memory; - pragma mmap_size = 30000000000; - pragma page_size = 32768; - pragma auto_vacuum = incremental; - pragma busy_timeout = 5000; + ctx := context.Background() + + conn, err := db.Conn(ctx) + if err != nil { + return nil, err + } + defer conn.Close() + + _, err = conn.ExecContext(ctx, ` create table if not exists registrations ( id integer primary key autoincrement, domain text not null unique, @@ -467,14 +476,14 @@ } // run migrations - runMigration(db, "add-description-to-repos", func(tx *sql.Tx) error { + runMigration(conn, "add-description-to-repos", func(tx *sql.Tx) error { tx.Exec(` alter table repos add column description text check (length(description) <= 200); `) return nil }) - runMigration(db, "add-rkey-to-pubkeys", func(tx *sql.Tx) error { + runMigration(conn, "add-rkey-to-pubkeys", func(tx *sql.Tx) error { // add unconstrained column _, err := tx.Exec(` alter table public_keys @@ -497,7 +506,7 @@ return nil }) - runMigration(db, "add-rkey-to-comments", func(tx *sql.Tx) error { + runMigration(conn, "add-rkey-to-comments", func(tx *sql.Tx) error { _, err := tx.Exec(` alter table comments drop column comment_at; alter table comments add column rkey text; @@ -505,7 +514,7 @@ return err }) - runMigration(db, "add-deleted-and-edited-to-issue-comments", func(tx *sql.Tx) error { + runMigration(conn, "add-deleted-and-edited-to-issue-comments", func(tx *sql.Tx) error { _, err := tx.Exec(` alter table comments add column deleted text; -- timestamp alter table comments add column edited text; -- timestamp @@ -513,7 +522,7 @@ return err }) - runMigration(db, "add-source-info-to-pulls-and-submissions", func(tx *sql.Tx) error { + runMigration(conn, "add-source-info-to-pulls-and-submissions", func(tx *sql.Tx) error { _, err := tx.Exec(` alter table pulls add column source_branch text; alter table pulls add column source_repo_at text; @@ -522,7 +531,7 @@ return err }) - runMigration(db, "add-source-to-repos", func(tx *sql.Tx) error { + runMigration(conn, "add-source-to-repos", func(tx *sql.Tx) error { _, err := tx.Exec(` alter table repos add column source text; `) @@ -533,8 +542,8 @@ // NOTE: this cannot be done in a transaction, so it is run outside [0] // // [0]: https://sqlite.org/pragma.html#pragma_foreign_keys - db.Exec("pragma foreign_keys = off;") - runMigration(db, "recreate-pulls-column-for-stacking-support", func(tx *sql.Tx) error { + conn.ExecContext(ctx, "pragma foreign_keys = off;") + runMigration(conn, "recreate-pulls-column-for-stacking-support", func(tx *sql.Tx) error { _, err := tx.Exec(` create table pulls_new ( -- identifiers @@ -589,10 +598,10 @@ `) return err }) - db.Exec("pragma foreign_keys = on;") + conn.ExecContext(ctx, "pragma foreign_keys = on;") // run migrations - runMigration(db, "add-spindle-to-repos", func(tx *sql.Tx) error { + runMigration(conn, "add-spindle-to-repos", func(tx *sql.Tx) error { tx.Exec(` alter table repos add column spindle text; `) @@ -600,7 +609,7 @@ }) // recreate and add rkey + created columns with default constraint - runMigration(db, "rework-collaborators-table", func(tx *sql.Tx) error { + runMigration(conn, "rework-collaborators-table", func(tx *sql.Tx) error { // create new table // - repo_at instead of repo integer // - rkey field @@ -659,8 +668,8 @@ type migrationFn = func(*sql.Tx) error -func runMigration(d *sql.DB, name string, migrationFn migrationFn) error { - tx, err := d.Begin() +func runMigration(c *sql.Conn, name string, migrationFn migrationFn) error { + tx, err := c.BeginTx(context.Background(), nil) if err != nil { return err } diff --git a/knotserver/db/init.go b/knotserver/db/init.go --- a/knotserver/db/init.go +++ b/knotserver/db/init.go @@ -2,6 +2,7 @@ import ( "database/sql" + "strings" _ "github.com/mattn/go-sqlite3" ) @@ -11,20 +12,24 @@ } func Setup(dbPath string) (*DB, error) { - db, err := sql.Open("sqlite3", dbPath+"?_foreign_keys=1") + // https://github.com/mattn/go-sqlite3#connection-string + opts := []string{ + "_foreign_keys=1", + "_journal_mode=WAL", + "_synchronous=NORMAL", + "_auto_vacuum=incremental", + } + + db, err := sql.Open("sqlite3", dbPath+"?"+strings.Join(opts, "&")) if err != nil { return nil, err } - _, err = db.Exec(` - pragma journal_mode = WAL; - pragma synchronous = normal; - pragma temp_store = memory; - pragma mmap_size = 30000000000; - pragma page_size = 32768; - pragma auto_vacuum = incremental; - pragma busy_timeout = 5000; + // NOTE: If any other migration is added here, you MUST + // copy the pattern in appview: use a single sql.Conn + // for every migration. + _, err = db.Exec(` create table if not exists known_dids ( did text primary key ); diff --git a/spindle/db/db.go b/spindle/db/db.go --- a/spindle/db/db.go +++ b/spindle/db/db.go @@ -2,6 +2,7 @@ import ( "database/sql" + "strings" _ "github.com/mattn/go-sqlite3" ) @@ -11,20 +12,24 @@ } func Make(dbPath string) (*DB, error) { - db, err := sql.Open("sqlite3", dbPath+"?_foreign_keys=1") + // https://github.com/mattn/go-sqlite3#connection-string + opts := []string{ + "_foreign_keys=1", + "_journal_mode=WAL", + "_synchronous=NORMAL", + "_auto_vacuum=incremental", + } + + db, err := sql.Open("sqlite3", dbPath+"?"+strings.Join(opts, "&")) if err != nil { return nil, err } - _, err = db.Exec(` - pragma journal_mode = WAL; - pragma synchronous = normal; - pragma temp_store = memory; - pragma mmap_size = 30000000000; - pragma page_size = 32768; - pragma auto_vacuum = incremental; - pragma busy_timeout = 5000; + // NOTE: If any other migration is added here, you MUST + // copy the pattern in appview: use a single sql.Conn + // for every migration. + _, err = db.Exec(` create table if not exists _jetstream ( id integer primary key autoincrement, last_time_us integer not null