From 4ff490806c826cf2da4c2291ed924f0a49383fce Mon Sep 17 00:00:00 2001 From: Julien Dessaux Date: Mon, 30 Sep 2024 00:58:49 +0200 Subject: feat(tfstated): implement GET and POST methods, states are encrypted in a sqlite3 database --- pkg/database/db.go | 103 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 pkg/database/db.go (limited to 'pkg/database/db.go') diff --git a/pkg/database/db.go b/pkg/database/db.go new file mode 100644 index 0000000..2744570 --- /dev/null +++ b/pkg/database/db.go @@ -0,0 +1,103 @@ +package database + +import ( + "context" + "database/sql" + "runtime" + + "git.adyxax.org/adyxax/tfstated/pkg/scrypto" +) + +func initDB(ctx context.Context, url string) (*sql.DB, error) { + db, err := sql.Open("sqlite3", url) + if err != nil { + return nil, err + } + defer func() { + if err != nil { + _ = db.Close() + } + }() + if _, err = db.ExecContext(ctx, "PRAGMA busy_timeout = 5000"); err != nil { + return nil, err + } + + return db, nil +} + +type DB struct { + ctx context.Context + dataEncryptionKey scrypto.AES256Key + readDB *sql.DB + writeDB *sql.DB +} + +func NewDB(ctx context.Context, url string) (*DB, error) { + readDB, err := initDB(ctx, url) + if err != nil { + return nil, err + } + defer func() { + if err != nil { + _ = readDB.Close() + } + }() + readDB.SetMaxOpenConns(max(4, runtime.NumCPU())) + + writeDB, err := initDB(ctx, url) + if err != nil { + return nil, err + } + defer func() { + if err != nil { + _ = writeDB.Close() + } + }() + writeDB.SetMaxOpenConns(1) + + db := DB{ + ctx: ctx, + readDB: readDB, + writeDB: writeDB, + } + if _, err = db.Exec("PRAGMA foreign_keys = ON"); err != nil { + return nil, err + } + if _, err = db.Exec("PRAGMA cache_size = 10000000"); err != nil { + return nil, err + } + if _, err = db.Exec("PRAGMA journal_mode = WAL"); err != nil { + return nil, err + } + if _, err = db.Exec("PRAGMA synchronous = NORMAL"); err != nil { + return nil, err + } + if err = db.migrate(); err != nil { + return nil, err + } + + return &db, nil +} + +func (db *DB) Begin() (*sql.Tx, error) { + return db.writeDB.Begin() +} + +func (db *DB) Close() error { + if err := db.readDB.Close(); err != nil { + _ = db.writeDB.Close() + } + return db.writeDB.Close() +} + +func (db *DB) Exec(query string, args ...any) (sql.Result, error) { + return db.writeDB.ExecContext(db.ctx, query, args...) +} + +func (db *DB) QueryRow(query string, args ...any) *sql.Row { + return db.readDB.QueryRowContext(db.ctx, query, args...) +} + +func (db *DB) SetDataEncryptionKey(s string) error { + return db.dataEncryptionKey.FromBase64(s) +} -- cgit v1.2.3