commit 326bdb5018ae81ee493371b56bd4564a8b35da59
parent 654cd518130db0a8ff3dd8f18504257bb4a37dd6
Author: lash <dev@holbrook.no>
Date:   Fri, 30 Aug 2024 17:58:10 +0100
Add documentation for db
Diffstat:
9 files changed, 87 insertions(+), 57 deletions(-)
diff --git a/db/db.go b/db/db.go
@@ -15,13 +15,23 @@ const (
 	DATATYPE_USERSTART
 )
 
+// Db abstracts all data storage and retrieval as a key-value store
 type Db interface {
+	// Connect prepares the storage backend for use
 	Connect(ctx context.Context, connStr string) error
+	// Close implements io.Closer
 	Close() error
+	// Get retrieves the value belonging to a key. Errors if the key does not exist, or if the retrieval otherwise fails.
 	Get(ctx context.Context, key []byte) ([]byte, error)
+	// Put stores a value under a key. Any existing value will be replaced. Errors if the value could not be stored.
 	Put(ctx context.Context, key []byte, val []byte) error
 }
 
+// ToDbKey generates a key to use Db to store a value for a particular context.
+//
+// If language is nil, then default language storage context will be used.
+//
+// If language is not nil, and the context does not support language, the language value will silently will be ignored.
 func ToDbKey(typ uint8, b []byte, l *lang.Language) []byte {
 	k := []byte{typ}
 	if l != nil && l.Code != "" {
@@ -31,19 +41,23 @@ func ToDbKey(typ uint8, b []byte, l *lang.Language) []byte {
 	return append(k, b...)
 }
 
+// BaseDb is a base class for all Db implementations.
 type BaseDb struct {
 	pfx uint8
 	sid []byte
 }
 
+// SetPrefix sets the storage context prefix to use for consecutive Get and Put operations.
 func(db *BaseDb) SetPrefix(pfx uint8) {
 	db.pfx = pfx
 }
 
+// SetSession sets the session context to use for consecutive Get and Put operations.
 func(db *BaseDb) SetSession(sessionId string) {
 	db.sid = append([]byte(sessionId), 0x2E)
 }
 
+// ToKey creates a DbKey within the current session context.
 func(db *BaseDb) ToKey(key []byte) ([]byte, error) {
 	if db.pfx == DATATYPE_UNKNOWN {
 		return nil, errors.New("datatype prefix cannot be UNKNOWN")
diff --git a/db/fs.go b/db/fs.go
@@ -8,11 +8,13 @@ import (
 	"path"
 )
 
+// FsDb is a pure filesystem backend implementation if the Db interface.
 type FsDb struct {
 	BaseDb
 	dir string
 }
 
+// Connect implements Db
 func(fdb *FsDb) Connect(ctx context.Context, connStr string) error {
 	fi, err := os.Stat(connStr)
 	if err != nil {
@@ -25,6 +27,7 @@ func(fdb *FsDb) Connect(ctx context.Context, connStr string) error {
 	return nil
 }
 
+// Get implements Db
 func(fdb *FsDb) Get(ctx context.Context, key []byte) ([]byte, error) {
 	fp, err := fdb.pathFor(key)
 	if err != nil {
@@ -42,6 +45,7 @@ func(fdb *FsDb) Get(ctx context.Context, key []byte) ([]byte, error) {
 	return b, nil
 }
 
+// Put implements Db
 func(fdb *FsDb) Put(ctx context.Context, key []byte, val []byte) error {
 	fp, err := fdb.pathFor(key)
 	if err != nil {
@@ -50,10 +54,12 @@ func(fdb *FsDb) Put(ctx context.Context, key []byte, val []byte) error {
 	return ioutil.WriteFile(fp, val, 0600)
 }
 
+// Close implements Db
 func(fdb *FsDb) Close() error {
 	return nil
 }	
- 
+
+// create a key safe for the filesystem
 func(fdb *FsDb) pathFor(key []byte) (string, error) {
 	kb, err := fdb.ToKey(key)
 	if err != nil {
diff --git a/db/fs_test.go b/db/fs_test.go
@@ -8,6 +8,7 @@ import (
 )
 
 func TestPutGetFs(t *testing.T) {
+	var dbi Db
 	ctx := context.Background()
 	sid := "ses"
 	d, err := ioutil.TempDir("", "vise-db-*")
@@ -17,6 +18,10 @@ func TestPutGetFs(t *testing.T) {
 	db := &FsDb{}
 	db.SetPrefix(DATATYPE_USERSTART)
 	db.SetSession(sid)
+
+	dbi = db
+	_ = dbi
+
 	err = db.Connect(ctx, d)
 	if err != nil {
 		t.Fatal(err)
diff --git a/db/gdbm.go b/db/gdbm.go
@@ -7,12 +7,14 @@ import (
 	gdbm "github.com/graygnuorg/go-gdbm"
 )
 
+// GdbmDb is a gdbm backend implementation of the Db interface.
 type GdbmDb struct {
 	BaseDb
 	conn *gdbm.Database
 	prefix uint8
 }
 
+// Connect implements Db
 func(gdb *GdbmDb) Connect(ctx context.Context, connStr string) error {
 	db, err := gdbm.Open(connStr, gdbm.ModeWrcreat)
 	if err != nil {
@@ -22,6 +24,7 @@ func(gdb *GdbmDb) Connect(ctx context.Context, connStr string) error {
 	return nil
 }
 
+// Put implements Db
 func(gdb *GdbmDb) Put(ctx context.Context, key []byte, val []byte) error {
 	k, err := gdb.ToKey(key)
 	if err != nil {
@@ -30,6 +33,7 @@ func(gdb *GdbmDb) Put(ctx context.Context, key []byte, val []byte) error {
 	return gdb.conn.Store(k, val, true)
 }
 
+// Get implements Db
 func(gdb *GdbmDb) Get(ctx context.Context, key []byte) ([]byte, error) {
 	k, err := gdb.ToKey(key)
 	if err != nil {
@@ -45,6 +49,7 @@ func(gdb *GdbmDb) Get(ctx context.Context, key []byte) ([]byte, error) {
 	return v, nil
 }
 
+// Close implements Db
 func(gdb *GdbmDb) Close() error {
 	return gdb.Close()
 }
diff --git a/db/gdbm_test.go b/db/gdbm_test.go
@@ -8,6 +8,7 @@ import (
 )
 
 func TestPutGetGdbm(t *testing.T) {
+	var dbi Db
 	ctx := context.Background()
 	sid := "ses"
 	f, err := ioutil.TempFile("", "vise-db-*")
@@ -17,6 +18,10 @@ func TestPutGetGdbm(t *testing.T) {
 	db := &GdbmDb{}
 	db.SetPrefix(DATATYPE_USERSTART)
 	db.SetSession(sid)
+
+	dbi = db
+	_ = dbi
+
 	err = db.Connect(ctx, f.Name())
 	if err != nil {
 		t.Fatal(err)
diff --git a/db/mem.go b/db/mem.go
@@ -5,21 +5,25 @@ import (
 	"fmt"
 )
 
+// MemDb is a memory backend implementation of the Db interface.
 type MemDb struct {
 	BaseDb
 	store map[string][]byte
 }
 
+// Connect implements Db
 func(mdb *MemDb) Connect(ctx context.Context, connStr string) error {
 	mdb.store = make(map[string][]byte)
 	return nil
 }
 
+// convert to a supported map key type
 func(mdb *MemDb) toHexKey(key []byte) (string, error) {
 	k, err := mdb.ToKey(key)
 	return fmt.Sprintf("%x", k), err
 }
 
+// Get implements Db
 func(mdb *MemDb) Get(ctx context.Context, key []byte) ([]byte, error) {
 	k, err := mdb.toHexKey(key)
 	if err != nil {
@@ -32,6 +36,7 @@ func(mdb *MemDb) Get(ctx context.Context, key []byte) ([]byte, error) {
 	return v, nil
 }
 
+// Put implements Db
 func(mdb *MemDb) Put(ctx context.Context, key []byte, val []byte) error {
 	k, err := mdb.toHexKey(key)
 	if err != nil {
@@ -41,6 +46,7 @@ func(mdb *MemDb) Put(ctx context.Context, key []byte, val []byte) error {
 	return nil
 }
 
+// Close implements Db
 func(mdb *MemDb) Close() error {
 	return nil
 }
diff --git a/db/mem_test.go b/db/mem_test.go
@@ -7,11 +7,16 @@ import (
 )
 
 func TestPutGetMem(t *testing.T) {
+	var dbi Db
 	ctx := context.Background()
 	sid := "ses"
 	db := &MemDb{}
 	db.SetPrefix(DATATYPE_USERSTART)
 	db.SetSession(sid)
+
+	dbi = db
+	_ = dbi
+
 	err := db.Connect(ctx, "")
 	if err != nil {
 		t.Fatal(err)
diff --git a/db/pg.go b/db/pg.go
@@ -7,6 +7,7 @@ import (
 	"github.com/jackc/pgx/v5/pgxpool"
 )
 
+// PgDb is a Postgresql backend implementation of the Db interface.
 type PgDb struct {
 	BaseDb
 	conn *pgxpool.Pool
@@ -14,17 +15,20 @@ type PgDb struct {
 	prefix uint8
 }
 
+// NewPgDb creates a new PgDb reference.
 func NewPgDb() *PgDb {
 	return &PgDb{
 		schema: "public",
 	}
 }
 
+// WithSchema sets the Postgres schema to use for the storage table.
 func(pdb *PgDb) WithSchema(schema string) *PgDb {
 	pdb.schema = schema
 	return pdb
 }
 
+// Connect implements Db.
 func(pdb *PgDb) Connect(ctx context.Context, connStr string) error {
 	var err error
 	conn, err := pgxpool.New(ctx, connStr)
@@ -35,61 +39,7 @@ func(pdb *PgDb) Connect(ctx context.Context, connStr string) error {
 	return pdb.prepare(ctx)
 }
 
-func(pdb *PgDb) prepare(ctx context.Context) error {
-	tx, err := pdb.conn.Begin(ctx)
-	if err != nil {
-		tx.Rollback(ctx)
-		return err
-	}
-//	query := fmt.Sprintf(`CREATE TABLE IF NOT EXISTS %s.kv_vise_domain (
-//		id SERIAL PRIMARY KEY,
-//		name VARCHAR(256) NOT NULL
-//	);
-//`, pdb.schema)
-//	_, err = tx.Exec(ctx, query)
-//	if err != nil {
-//		tx.Rollback(ctx)
-//		return err
-//	}
-//
-//	query = fmt.Sprintf(`CREATE TABLE IF NOT EXISTS %s.kv_vise (
-//		id SERIAL NOT NULL,
-//		domain_id INT NOT NULL,
-//		key VARCHAR(256) NOT NULL,
-//		value BYTEA NOT NULL,
-//		constraint fk_domain
-//			FOREIGN KEY (domain_id)
-//			REFERENCES %s.kv_vise_domain(id)
-//	);
-//`, pdb.schema, pdb.schema)
-//	_, err = tx.Exec(ctx, query)
-//	if err != nil {
-//		tx.Rollback(ctx)
-//		return err
-//	}
-
-	query := fmt.Sprintf(`CREATE TABLE IF NOT EXISTS %s.kv_vise (
-		id SERIAL NOT NULL,
-		key BYTEA NOT NULL UNIQUE,
-		value BYTEA NOT NULL
-	);
-`, pdb.schema)
-	_, err = tx.Exec(ctx, query)
-	if err != nil {
-		tx.Rollback(ctx)
-		return err
-	}
-
-	err = tx.Commit(ctx)
-	if err != nil {
-		//if !errors.Is(pgx.ErrTxCommitRollback) {
-			tx.Rollback(ctx)
-			return err
-		//}
-	}
-	return nil
-}
-
+// Put implements Db.
 func(pdb *PgDb) Put(ctx context.Context, key []byte, val []byte) error {
 	k, err := pdb.ToKey(key)
 	if err != nil {
@@ -109,6 +59,7 @@ func(pdb *PgDb) Put(ctx context.Context, key []byte, val []byte) error {
 	return nil
 }
 
+// Get implements Db.
 func(pdb *PgDb) Get(ctx context.Context, key []byte) ([]byte, error) {
 	k, err := pdb.ToKey(key)
 	if err != nil {
@@ -133,7 +84,35 @@ func(pdb *PgDb) Get(ctx context.Context, key []byte) ([]byte, error) {
 	return b, nil
 }
 
+// Close implements Db.
 func(pdb *PgDb) Close() error {
 	pdb.Close()
 	return nil
 }
+
+// set up table
+func(pdb *PgDb) prepare(ctx context.Context) error {
+	tx, err := pdb.conn.Begin(ctx)
+	if err != nil {
+		tx.Rollback(ctx)
+		return err
+	}
+	query := fmt.Sprintf(`CREATE TABLE IF NOT EXISTS %s.kv_vise (
+		id SERIAL NOT NULL,
+		key BYTEA NOT NULL UNIQUE,
+		value BYTEA NOT NULL
+	);
+`, pdb.schema)
+	_, err = tx.Exec(ctx, query)
+	if err != nil {
+		tx.Rollback(ctx)
+		return err
+	}
+
+	err = tx.Commit(ctx)
+	if err != nil {
+		tx.Rollback(ctx)
+		return err
+	}
+	return nil
+}
diff --git a/db/pg_test.go b/db/pg_test.go
@@ -7,12 +7,17 @@ import (
 )
 
 func TestPutGetPg(t *testing.T) {
-	t.Skip("need postgresql mock")
+	var dbi Db
 	ses := "xyzzy"
 	db := NewPgDb().WithSchema("vvise")
 	db.SetPrefix(DATATYPE_USERSTART)
 	db.SetSession(ses)
 	ctx := context.Background()
+
+	dbi = db
+	_ = dbi
+
+	t.Skip("need postgresql mock")
 	err := db.Connect(ctx, "postgres://vise:esiv@localhost:5432/visedb")
 	if err != nil {
 		t.Fatal(err)