summaryrefslogtreecommitdiff
path: root/srv/src
diff options
context:
space:
mode:
Diffstat (limited to 'srv/src')
-rw-r--r--srv/src/cfg/data_dir.go74
-rw-r--r--srv/src/cfg/mediocre_blog.go9
-rw-r--r--srv/src/cmd/mailinglist-cli/main.go16
-rw-r--r--srv/src/cmd/mediocre-blog/main.go16
-rw-r--r--srv/src/mailinglist/store.go14
-rw-r--r--srv/src/mailinglist/store_test.go23
-rw-r--r--srv/src/post/store.go11
-rw-r--r--srv/src/post/store_test.go22
8 files changed, 127 insertions, 58 deletions
diff --git a/srv/src/cfg/data_dir.go b/srv/src/cfg/data_dir.go
new file mode 100644
index 0000000..649bc15
--- /dev/null
+++ b/srv/src/cfg/data_dir.go
@@ -0,0 +1,74 @@
+package cfg
+
+import (
+ "context"
+ "fmt"
+ "os"
+
+ "github.com/mediocregopher/mediocre-go-lib/v2/mctx"
+)
+
+// DataDir manages the blog's data directory.
+type DataDir struct {
+ Path string
+
+ deleteOnClose bool
+}
+
+// Init initializes the data directory, creating the directory named at path if
+// it doesn't exist.
+//
+// If Path is not set, then a temporary directory will be created and its path
+// set to the Path field. This directory will be removed when Close is called.
+func (d *DataDir) Init() error {
+ if d.Path == "" {
+
+ d.deleteOnClose = true
+ var err error
+
+ if d.Path, err = os.MkdirTemp("", "mediocre-blog-data-*"); err != nil {
+ return fmt.Errorf("creating temporary directory: %w", err)
+ }
+
+ return nil
+ }
+
+ if err := os.MkdirAll(d.Path, 0700); err != nil {
+ return fmt.Errorf(
+ "creating directory (and parents) of %q: %w",
+ d.Path,
+ err,
+ )
+ }
+
+ return nil
+}
+
+// SetupCfg implement the cfg.Cfger interface.
+func (d *DataDir) SetupCfg(cfg *Cfg) {
+
+ cfg.StringVar(&d.Path, "data-dir", "", "Directory to use for persistent storage. If unset a temp directory will be created, and will be deleted when the process exits.")
+
+ cfg.OnInit(func(ctx context.Context) error {
+ return d.Init()
+ })
+}
+
+// Annotate implements mctx.Annotator interface.
+func (d *DataDir) Annotate(a mctx.Annotations) {
+ a["dataDirPath"] = d.Path
+}
+
+// Close cleans up any temporary state created by DataDir.
+func (d *DataDir) Close() error {
+
+ if !d.deleteOnClose {
+ return nil
+ }
+
+ if err := os.RemoveAll(d.Path); err != nil {
+ return fmt.Errorf("removing temp dir %q: %w", d.Path, err)
+ }
+
+ return nil
+}
diff --git a/srv/src/cfg/mediocre_blog.go b/srv/src/cfg/mediocre_blog.go
new file mode 100644
index 0000000..98fe08c
--- /dev/null
+++ b/srv/src/cfg/mediocre_blog.go
@@ -0,0 +1,9 @@
+package cfg
+
+// this file contains functionality specific to the mediocre blog.
+
+// NewBlogCfg returns a Cfg specifically configured for mediocre blog processes.
+func NewBlogCfg(params Params) *Cfg {
+ params.EnvPrefix = "MEDIOCRE_BLOG"
+ return New(params)
+}
diff --git a/srv/src/cmd/mailinglist-cli/main.go b/srv/src/cmd/mailinglist-cli/main.go
index c3207df..c090f41 100644
--- a/srv/src/cmd/mailinglist-cli/main.go
+++ b/srv/src/cmd/mailinglist-cli/main.go
@@ -4,9 +4,9 @@ import (
"context"
"errors"
"io"
- "path"
"github.com/mediocregopher/blog.mediocregopher.com/srv/cfg"
+ cfgpkg "github.com/mediocregopher/blog.mediocregopher.com/srv/cfg"
"github.com/mediocregopher/blog.mediocregopher.com/srv/mailinglist"
"github.com/mediocregopher/mediocre-go-lib/v2/mctx"
"github.com/mediocregopher/mediocre-go-lib/v2/mlog"
@@ -17,11 +17,12 @@ func main() {
ctx := context.Background()
- cfg := cfg.New(cfg.Params{
- EnvPrefix: "MEDIOCRE_BLOG",
- })
+ cfg := cfgpkg.NewBlogCfg(cfg.Params{})
- dataDir := cfg.String("data-dir", ".", "Directory to use for long term storage")
+ var dataDir cfgpkg.DataDir
+ dataDir.SetupCfg(cfg)
+ defer dataDir.Close()
+ ctx = mctx.WithAnnotator(ctx, &dataDir)
var mailerParams mailinglist.MailerParams
mailerParams.SetupCfg(cfg)
@@ -54,10 +55,7 @@ func main() {
mailer = mailinglist.NewMailer(mailerParams)
}
- mailingListDBFile := path.Join(*dataDir, "mailinglist.sqlite3")
- ctx = mctx.Annotate(ctx, "mailingListDBFile", mailingListDBFile)
-
- mlStore, err := mailinglist.NewStore(mailingListDBFile)
+ mlStore, err := mailinglist.NewStore(dataDir)
if err != nil {
logger.Fatal(ctx, "initializing mailing list storage", err)
}
diff --git a/srv/src/cmd/mediocre-blog/main.go b/srv/src/cmd/mediocre-blog/main.go
index 4cf3024..58a43e9 100644
--- a/srv/src/cmd/mediocre-blog/main.go
+++ b/srv/src/cmd/mediocre-blog/main.go
@@ -4,12 +4,12 @@ import (
"context"
"os"
"os/signal"
- "path"
"syscall"
"time"
"github.com/mediocregopher/blog.mediocregopher.com/srv/api"
"github.com/mediocregopher/blog.mediocregopher.com/srv/cfg"
+ cfgpkg "github.com/mediocregopher/blog.mediocregopher.com/srv/cfg"
"github.com/mediocregopher/blog.mediocregopher.com/srv/chat"
"github.com/mediocregopher/blog.mediocregopher.com/srv/mailinglist"
"github.com/mediocregopher/blog.mediocregopher.com/srv/pow"
@@ -23,11 +23,12 @@ func main() {
ctx := context.Background()
- cfg := cfg.New(cfg.Params{
- EnvPrefix: "MEDIOCRE_BLOG",
- })
+ cfg := cfg.NewBlogCfg(cfg.Params{})
- dataDir := cfg.String("data-dir", ".", "Directory to use for long term storage")
+ var dataDir cfgpkg.DataDir
+ dataDir.SetupCfg(cfg)
+ defer dataDir.Close()
+ ctx = mctx.WithAnnotator(ctx, &dataDir)
var powMgrParams pow.ManagerParams
powMgrParams.SetupCfg(cfg)
@@ -91,10 +92,7 @@ func main() {
mailer = mailinglist.NewMailer(mailerParams)
}
- mailingListDBFile := path.Join(*dataDir, "mailinglist.sqlite3")
- ctx = mctx.Annotate(ctx, "mailingListDBFile", mailingListDBFile)
-
- mlStore, err := mailinglist.NewStore(mailingListDBFile)
+ mlStore, err := mailinglist.NewStore(dataDir)
if err != nil {
logger.Fatal(ctx, "initializing mailing list storage", err)
}
diff --git a/srv/src/mailinglist/store.go b/srv/src/mailinglist/store.go
index a7a210f..49e7617 100644
--- a/srv/src/mailinglist/store.go
+++ b/srv/src/mailinglist/store.go
@@ -7,10 +7,12 @@ import (
"errors"
"fmt"
"io"
+ "path"
"strings"
"time"
_ "github.com/mattn/go-sqlite3"
+ "github.com/mediocregopher/blog.mediocregopher.com/srv/cfg"
migrate "github.com/rubenv/sql-migrate"
)
@@ -83,13 +85,15 @@ type store struct {
db *sql.DB
}
-// NewStore initializes a new Store using a sqlite3 database at the given file
-// path.
-func NewStore(dbFile string) (Store, error) {
+// NewStore initializes a new Store using a sqlite3 database in the given
+// DataDir.
+func NewStore(dataDir cfg.DataDir) (Store, error) {
- db, err := sql.Open("sqlite3", dbFile)
+ path := path.Join(dataDir.Path, "mailinglist.sqlite3")
+
+ db, err := sql.Open("sqlite3", path)
if err != nil {
- return nil, fmt.Errorf("opening sqlite file: %w", err)
+ return nil, fmt.Errorf("opening sqlite file at %q: %w", path, err)
}
migrations := &migrate.MemoryMigrationSource{Migrations: migrations}
diff --git a/srv/src/mailinglist/store_test.go b/srv/src/mailinglist/store_test.go
index 25eb150..9093d90 100644
--- a/srv/src/mailinglist/store_test.go
+++ b/srv/src/mailinglist/store_test.go
@@ -2,31 +2,24 @@ package mailinglist
import (
"io"
- "io/ioutil"
- "os"
"testing"
"time"
+ "github.com/mediocregopher/blog.mediocregopher.com/srv/cfg"
"github.com/stretchr/testify/assert"
)
func TestStore(t *testing.T) {
- tmpFile, err := ioutil.TempFile(os.TempDir(), "mediocre-blog-mailinglist-store-test-")
- if err != nil {
- t.Fatal("Cannot create temporary file", err)
- }
- tmpFilePath := tmpFile.Name()
- tmpFile.Close()
- t.Logf("using temporary sqlite file at %q", tmpFilePath)
+ var dataDir cfg.DataDir
- t.Cleanup(func() {
- if err := os.Remove(tmpFilePath); err != nil {
- panic(err)
- }
- })
+ if err := dataDir.Init(); err != nil {
+ t.Fatal(err)
+ }
+
+ t.Cleanup(func() { dataDir.Close() })
- store, err := NewStore(tmpFilePath)
+ store, err := NewStore(dataDir)
assert.NoError(t, err)
t.Cleanup(func() {
diff --git a/srv/src/post/store.go b/srv/src/post/store.go
index 3f044e2..6bdccc2 100644
--- a/srv/src/post/store.go
+++ b/srv/src/post/store.go
@@ -9,6 +9,7 @@ import (
"time"
_ "github.com/mattn/go-sqlite3" // we need dis
+ "github.com/mediocregopher/blog.mediocregopher.com/srv/cfg"
migrate "github.com/rubenv/sql-migrate"
)
@@ -99,9 +100,7 @@ var migrations = []*migrate.Migration{
// Params are parameters used to initialize a new Store. All fields are required
// unless otherwise noted.
type StoreParams struct {
-
- // Path to the file the database will be stored at.
- DBFilePath string
+ DataDir cfg.DataDir
}
type store struct {
@@ -113,9 +112,11 @@ type store struct {
// path.
func NewStore(params StoreParams) (Store, error) {
- db, err := sql.Open("sqlite3", params.DBFilePath)
+ path := path.Join(params.DataDir.Path, "post.sqlite3")
+
+ db, err := sql.Open("sqlite3", path)
if err != nil {
- return nil, fmt.Errorf("opening sqlite file: %w", err)
+ return nil, fmt.Errorf("opening sqlite file at %q: %w", path, err)
}
migrations := &migrate.MemoryMigrationSource{Migrations: migrations}
diff --git a/srv/src/post/store_test.go b/srv/src/post/store_test.go
index 9b0ee45..1b4fb30 100644
--- a/srv/src/post/store_test.go
+++ b/srv/src/post/store_test.go
@@ -1,13 +1,12 @@
package post
import (
- "io/ioutil"
- "os"
"sort"
"strconv"
"testing"
"time"
+ "github.com/mediocregopher/blog.mediocregopher.com/srv/cfg"
"github.com/stretchr/testify/assert"
"github.com/tilinna/clock"
)
@@ -29,25 +28,18 @@ type storeTestHarness struct {
func newStoreTestHarness(t *testing.T) storeTestHarness {
- clock := clock.NewMock(time.Now().UTC().Truncate(1 * time.Hour))
+ var dataDir cfg.DataDir
- tmpFile, err := ioutil.TempFile(os.TempDir(), "mediocre-blog-post-store-test-")
- if err != nil {
- t.Fatal("Cannot create temporary file", err)
+ if err := dataDir.Init(); err != nil {
+ t.Fatal(err)
}
- tmpFilePath := tmpFile.Name()
- tmpFile.Close()
- t.Logf("using temporary sqlite file at %q", tmpFilePath)
+ t.Cleanup(func() { dataDir.Close() })
- t.Cleanup(func() {
- if err := os.Remove(tmpFilePath); err != nil {
- panic(err)
- }
- })
+ clock := clock.NewMock(time.Now().UTC().Truncate(1 * time.Hour))
store, err := NewStore(StoreParams{
- DBFilePath: tmpFilePath,
+ DataDir: dataDir,
})
assert.NoError(t, err)