summaryrefslogtreecommitdiff
path: root/srv/src/post
diff options
context:
space:
mode:
authorBrian Picciano <mediocregopher@gmail.com>2022-05-07 14:56:34 -0600
committerBrian Picciano <mediocregopher@gmail.com>2022-05-07 14:56:34 -0600
commit07806c694269f6226a0f42c9f2cfb8c7655afad9 (patch)
tree7ea36474ab384bc59daa405f5789071993fc0ccf /srv/src/post
parent1495c78656c94396c35c5eef5838e2d0f5cce4bf (diff)
Move sql db out of post.NewStore, so it can be shared
Diffstat (limited to 'srv/src/post')
-rw-r--r--srv/src/post/sql.go69
-rw-r--r--srv/src/post/store.go69
-rw-r--r--srv/src/post/store_test.go14
3 files changed, 84 insertions, 68 deletions
diff --git a/srv/src/post/sql.go b/srv/src/post/sql.go
new file mode 100644
index 0000000..fb9468f
--- /dev/null
+++ b/srv/src/post/sql.go
@@ -0,0 +1,69 @@
+package post
+
+import (
+ "database/sql"
+ "fmt"
+ "path"
+
+ "github.com/mediocregopher/blog.mediocregopher.com/srv/cfg"
+ migrate "github.com/rubenv/sql-migrate"
+)
+
+var migrations = []*migrate.Migration{
+ &migrate.Migration{
+ Id: "1",
+ Up: []string{
+ `CREATE TABLE posts (
+ id TEXT NOT NULL PRIMARY KEY,
+ title TEXT NOT NULL,
+ description TEXT NOT NULL,
+ series TEXT,
+
+ published_at INTEGER NOT NULL,
+ last_updated_at INTEGER,
+
+ body TEXT NOT NULL
+ )`,
+ `CREATE TABLE post_tags (
+ post_id TEXT NOT NULL,
+ tag TEXT NOT NULL,
+ UNIQUE(post_id, tag)
+ )`,
+ },
+ Down: []string{
+ "DROP TABLE post_tags",
+ "DROP TABLE posts",
+ },
+ },
+}
+
+// SQLDB is a sqlite3 database which can be used by storage interfaces within
+// this package.
+type SQLDB struct {
+ db *sql.DB
+}
+
+// NewSQLDB initializes and returns a new sqlite3 database for post storage
+// intefaces. The db will be created within the given data directory.
+func NewSQLDB(dataDir cfg.DataDir) (*SQLDB, error) {
+
+ path := path.Join(dataDir.Path, "post.sqlite3")
+
+ db, err := sql.Open("sqlite3", path)
+ if err != nil {
+ return nil, fmt.Errorf("opening sqlite file at %q: %w", path, err)
+ }
+
+ migrations := &migrate.MemoryMigrationSource{Migrations: migrations}
+
+ if _, err := migrate.Exec(db, "sqlite3", migrations, migrate.Up); err != nil {
+ return nil, fmt.Errorf("running migrations: %w", err)
+ }
+
+ return &SQLDB{db}, nil
+}
+
+// Close cleans up loose resources being held by the db.
+func (db *SQLDB) Close() error {
+ return db.db.Close()
+}
diff --git a/srv/src/post/store.go b/srv/src/post/store.go
index 6bdccc2..5da17a9 100644
--- a/srv/src/post/store.go
+++ b/srv/src/post/store.go
@@ -9,8 +9,6 @@ import (
"time"
_ "github.com/mattn/go-sqlite3" // we need dis
- "github.com/mediocregopher/blog.mediocregopher.com/srv/cfg"
- migrate "github.com/rubenv/sql-migrate"
)
var (
@@ -69,66 +67,15 @@ type Store interface {
Close() error
}
-var migrations = []*migrate.Migration{
- &migrate.Migration{
- Id: "1",
- Up: []string{
- `CREATE TABLE posts (
- id TEXT NOT NULL PRIMARY KEY,
- title TEXT NOT NULL,
- description TEXT NOT NULL,
- series TEXT,
-
- published_at INTEGER NOT NULL,
- last_updated_at INTEGER,
-
- body TEXT NOT NULL
- )`,
- `CREATE TABLE post_tags (
- post_id TEXT NOT NULL,
- tag TEXT NOT NULL,
- UNIQUE(post_id, tag)
- )`,
- },
- Down: []string{
- "DROP TABLE post_tags",
- "DROP TABLE posts",
- },
- },
-}
-
-// Params are parameters used to initialize a new Store. All fields are required
-// unless otherwise noted.
-type StoreParams struct {
- DataDir cfg.DataDir
-}
-
type store struct {
- params StoreParams
- db *sql.DB
+ db *sql.DB
}
-// NewStore initializes a new Store using a sqlite3 database at the given file
-// path.
-func NewStore(params StoreParams) (Store, error) {
-
- path := path.Join(params.DataDir.Path, "post.sqlite3")
-
- db, err := sql.Open("sqlite3", path)
- if err != nil {
- return nil, fmt.Errorf("opening sqlite file at %q: %w", path, err)
- }
-
- migrations := &migrate.MemoryMigrationSource{Migrations: migrations}
-
- if _, err := migrate.Exec(db, "sqlite3", migrations, migrate.Up); err != nil {
- return nil, fmt.Errorf("running migrations: %w", err)
- }
-
+// NewStore initializes a new Store using an existing SQLDB.
+func NewStore(db *SQLDB) Store {
return &store{
- params: params,
- db: db,
- }, nil
+ db: db.db,
+ }
}
func (s *store) Close() error {
@@ -168,7 +115,7 @@ func (s *store) Set(post Post, now time.Time) error {
nowTS := now.Unix()
- nowSql := sql.NullInt64{Int64: nowTS, Valid: !now.IsZero()}
+ nowSQL := sql.NullInt64{Int64: nowTS, Valid: !now.IsZero()}
_, err := tx.Exec(
`INSERT INTO posts (
@@ -186,9 +133,9 @@ func (s *store) Set(post Post, now time.Time) error {
post.Title,
post.Description,
&sql.NullString{String: post.Series, Valid: post.Series != ""},
- nowSql,
+ nowSQL,
post.Body,
- nowSql,
+ nowSQL,
)
if err != nil {
diff --git a/srv/src/post/store_test.go b/srv/src/post/store_test.go
index 1b4fb30..3ccf5d7 100644
--- a/srv/src/post/store_test.go
+++ b/srv/src/post/store_test.go
@@ -38,14 +38,14 @@ func newStoreTestHarness(t *testing.T) storeTestHarness {
clock := clock.NewMock(time.Now().UTC().Truncate(1 * time.Hour))
- store, err := NewStore(StoreParams{
- DataDir: dataDir,
- })
- assert.NoError(t, err)
+ db, err := NewSQLDB(dataDir)
+ if err != nil {
+ t.Fatal(err)
+ }
- t.Cleanup(func() {
- assert.NoError(t, store.Close())
- })
+ t.Cleanup(func() { db.Close() })
+
+ store := NewStore(db)
return storeTestHarness{
clock: clock,