Skip to content
This repository has been archived by the owner on Apr 12, 2023. It is now read-only.

treemanager: Expose read-only mode and fast reads #25

Merged
merged 1 commit into from
Dec 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 28 additions & 14 deletions cmd/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"net/http"
"os"
"os/signal"
"time"

"github.com/spf13/cobra"
"github.com/spf13/viper"
Expand All @@ -24,11 +23,6 @@ import (
dbutils "github.com/infratographer/fertilesoil/storage/crdb/utils"
)

const (
defaultListen = ":8080"
defaultServerShutdownTimeout = 5 * time.Second
)

// serveCmd represents the treemanager command.
var serveCmd = &cobra.Command{
Use: "serve",
Expand All @@ -48,18 +42,36 @@ func init() {

v := viper.GetViper()
dbutils.RegisterDBArgs(v, serveCmd.Flags())
ginx.MustViperFlags(v, serveCmd.Flags(), defaultListen)
ginx.MustViperFlags(v, serveCmd.Flags(), treemanager.DefaultTreeManagerListen)
loggingx.MustViperFlags(v, serveCmd.Flags())
natsutils.RegisterNATSArgs(v, serveCmd.Flags())

// TODO(jaosorior): Add tracing
// TODO(jaosorior): Add metrics
// TODO(jaosorior): Add TLS flags

// Server flags
flags := serveCmd.Flags()

// server shutdown timeout
flags.Duration("server-shutdown-timeout",
defaultServerShutdownTimeout,
treemanager.DefaultTreeManagerShutdownTimeout,
"Time to wait for the server to shutdown gracefully")
viperx.MustBindFlag(v, "server.shutdown", flags.Lookup("server-shutdown-timeout"))
flags.String("server-unix-socket", "", "Listen on a unix socket instead of a TCP socket.")

// server UNIX socket
flags.String("server-unix-socket",
treemanager.DefaultTreeManagerUnix,
"Listen on a unix socket instead of a TCP socket.")
viperx.MustBindFlag(v, "server.unix_socket", flags.Lookup("server-unix-socket"))

// read-only mode
flags.Bool("read-only", treemanager.DefaultTreeManagerReadOnly, "Run the server in read-only mode.")
viperx.MustBindFlag(v, "server.read_only", flags.Lookup("read-only"))

// fast reads
flags.Bool("fast-reads", treemanager.DefaultTreeManagerFastReads, "Run the server in fast reads mode.")
viperx.MustBindFlag(v, "server.fast_reads", flags.Lookup("fast-reads"))
}

func serverRunE(cmd *cobra.Command, args []string) error {
Expand Down Expand Up @@ -99,12 +111,14 @@ func serverRunE(cmd *cobra.Command, args []string) error {

s := treemanager.NewServer(
l,
viper.GetString("listen"),
db,
viper.GetBool("debug"),
viper.GetDuration("server.shutdown"),
viper.GetString("server.unix_socket"),
notif,
treemanager.WithListen(v.GetString("server.listen")),
treemanager.WithUnix(v.GetString("server.unix_socket")),
treemanager.WithDebug(v.GetBool("debug")),
treemanager.WithReadOnly(v.GetBool("server.read_only")),
treemanager.WithFastReads(v.GetBool("server.fast_reads")),
treemanager.WithShutdownTimeout(v.GetDuration("server.shutdown")),
treemanager.WithNotifier(notif),
)

go func() {
Expand Down
3 changes: 0 additions & 3 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-contrib/zap v0.1.0 h1:RMSFFJo34XZogV62OgOzvrlaMNmXrNxmJ3bFmMwl6Cc=
github.com/gin-contrib/zap v0.1.0/go.mod h1:hvnZaPs478H1PGvRP8w89ZZbyJUiyip4ddiI/53WG3o=
github.com/gin-gonic/gin v1.8.1 h1:4+fr/el88TOO3ewCmQr8cx/CtZ/umlIRIs5M4NTNjf8=
github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk=
github.com/gin-gonic/gin v1.8.2 h1:UzKToD9/PoFj/V4rvlKqTRKnQYyz8Sc1MJlv4JHPtvY=
github.com/gin-gonic/gin v1.8.2/go.mod h1:qw5AYuDrzRTnhvusDsrov+fDIxp9Dleuu12h8nfB398=
Expand Down Expand Up @@ -305,8 +304,6 @@ github.com/nats-io/jwt/v2 v2.3.0 h1:z2mA1a7tIf5ShggOFlR1oBPgd6hGqcDYsISxZByUzdI=
github.com/nats-io/jwt/v2 v2.3.0/go.mod h1:0tqz9Hlu6bCBFLWAASKhE5vUA4c24L9KPUUgvwumE/k=
github.com/nats-io/nats-server/v2 v2.9.10 h1:LMC46Oi9E6BUx/xBsaCVZgofliAqKQzRPU6eKWkN8jE=
github.com/nats-io/nats-server/v2 v2.9.10/go.mod h1:AB6hAnGZDlYfqb7CTAm66ZKMZy9DpfierY1/PbpvI2g=
github.com/nats-io/nats.go v1.22.0 h1:3dxyVf+S449DbMriqQV27HgSbXklxT9SUKbDKIxhrV0=
github.com/nats-io/nats.go v1.22.0/go.mod h1:tLqubohF7t4z3du1QDPYJIQQyhb4wl6DhjxEajSI7UA=
github.com/nats-io/nats.go v1.22.1 h1:XzfqDspY0RNufzdrB8c4hFR+R3dahkxlpWe5+IWJzbE=
github.com/nats-io/nats.go v1.22.1/go.mod h1:tLqubohF7t4z3du1QDPYJIQQyhb4wl6DhjxEajSI7UA=
github.com/nats-io/nkeys v0.3.0 h1:cgM5tL53EvYRU+2YLXIK0G2mJtK12Ft9oeooSZMA2G8=
Expand Down
100 changes: 100 additions & 0 deletions internal/httpsrv/treemanager/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package treemanager

import (
"time"

"github.com/infratographer/fertilesoil/notifier"
"github.com/infratographer/fertilesoil/notifier/noop"
"github.com/infratographer/fertilesoil/storage/crdb/driver"
)

type treeManagerConfig struct {
listen string
unix string
debug bool
readonly bool
fastReads bool
shutdownTimeout time.Duration
notif notifier.Notifier
}

type Option func(*treeManagerConfig)

// WithListen sets the listen address for the server.
func WithListen(listen string) Option {
return func(c *treeManagerConfig) {
c.listen = listen
}
}

// WithUnix sets the unix socket for the server.
// If set, the server will listen on the unix socket
// instead of the listen address.
func WithUnix(unix string) Option {
return func(c *treeManagerConfig) {
c.unix = unix
}
}

// WithDebug sets the debug flag for the server.
func WithDebug(debug bool) Option {
return func(c *treeManagerConfig) {
c.debug = debug
}
}

// WithReadOnly sets the readonly flag for the server.
// If true, the server will use the readonly flag when
// reading from the database.
func WithReadOnly(readonly bool) Option {
return func(c *treeManagerConfig) {
c.readonly = readonly
}
}

// WithFastReads sets the fastReads flag for the server.
// If true, the server will use the fastReads flag when
// reading from the database. This will cause the server
// to read from the database without waiting for the
// database to commit the transaction. This is useful
// for read-heavy workloads, but can cause data to be
// out of sync with the database.
func WithFastReads(fastReads bool) Option {
return func(c *treeManagerConfig) {
c.fastReads = fastReads
}
}

// WithShutdownTimeout sets the shutdown timeout for the server.
func WithShutdownTimeout(t time.Duration) Option {
return func(c *treeManagerConfig) {
c.shutdownTimeout = t
}
}

// WithNotifier sets the notifier for the server.
func WithNotifier(n notifier.Notifier) Option {
return func(c *treeManagerConfig) {
if n == nil {
n = noop.NewNotifier()
}
c.notif = n
}
}

func (c *treeManagerConfig) apply(opts ...Option) {
for _, opt := range opts {
opt(c)
}
}

func (c *treeManagerConfig) withStorageDriverOptions() []driver.Options {
opts := []driver.Options{}
if c.readonly {
opts = append(opts, driver.WithReadOnly())
}
if c.fastReads {
opts = append(opts, driver.WithFastReads())
}
return opts
}
25 changes: 25 additions & 0 deletions internal/httpsrv/treemanager/defaults.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package treemanager

import (
"time"

"github.com/infratographer/fertilesoil/notifier/noop"
)

const (
// DefaultTreeManagerListen is the default listen address for the TreeManager.
DefaultTreeManagerListen = ":8080"
// DefaultTreeManagerUnix is the default unix socket for the TreeManager.
DefaultTreeManagerUnix = ""
// DefaultTreeManagerDebug is the default debug flag for the TreeManager.
DefaultTreeManagerDebug = false
// DefaultTreeManagerReadOnly is the default read-only flag for the TreeManager.
DefaultTreeManagerReadOnly = false
// DefaultTreeManagerFastReads is the default fast reads flag for the TreeManager.
DefaultTreeManagerFastReads = false
// DefaultTreeManagerShutdownTimeout is the default shutdown timeout for the TreeManager.
DefaultTreeManagerShutdownTimeout = 5 * time.Second
)

// DefaultTreeManagerNotifier is the default notifier for the TreeManager.
var DefaultTreeManagerNotifier = noop.NewNotifier()
31 changes: 14 additions & 17 deletions internal/httpsrv/treemanager/treemanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,41 +5,38 @@ import (
"database/sql"
"errors"
"net/http"
"time"

"github.com/gin-gonic/gin"
"go.uber.org/zap"

v1 "github.com/infratographer/fertilesoil/api/v1"
"github.com/infratographer/fertilesoil/internal/httpsrv/common"
"github.com/infratographer/fertilesoil/notifier"
"github.com/infratographer/fertilesoil/notifier/noop"
"github.com/infratographer/fertilesoil/storage"
"github.com/infratographer/fertilesoil/storage/crdb/driver"
sn "github.com/infratographer/fertilesoil/storage/notifier"
)

func NewServer(
logger *zap.Logger,
listen string,
db *sql.DB,
debug bool,
shutdownTime time.Duration,
unix string,
n notifier.Notifier,
opts ...Option,
) *common.Server {
dbdrv := driver.NewDirectoryDriver(db)
cfg := &treeManagerConfig{
listen: DefaultTreeManagerListen,
unix: DefaultTreeManagerUnix,
debug: DefaultTreeManagerDebug,
readonly: DefaultTreeManagerReadOnly,
fastReads: DefaultTreeManagerFastReads,
shutdownTimeout: DefaultTreeManagerShutdownTimeout,
notif: DefaultTreeManagerNotifier,
}
cfg.apply(opts...)

var notif notifier.Notifier
dbdrv := driver.NewDirectoryDriver(db, cfg.withStorageDriverOptions()...)

if n == nil {
notif = noop.NewNotifier()
} else {
notif = n
}
store := sn.StorageWithNotifier(dbdrv, cfg.notif, sn.WithNotifyRetrier())

store := sn.StorageWithNotifier(dbdrv, notif, sn.WithNotifyRetrier())
s := common.NewServer(logger, listen, db, store, debug, shutdownTime, unix)
s := common.NewServer(logger, cfg.listen, db, store, cfg.debug, cfg.shutdownTimeout, cfg.unix)

s.SetHandler(newHandler(logger, s))

Expand Down
9 changes: 8 additions & 1 deletion tests/integration/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,14 @@ func TestServerWithBadDB(t *testing.T) {
dbconn, err := sql.Open("postgres", baseDBURL.String())
assert.NoError(t, err, "error creating db connection")

srv := treemanager.NewServer(tl, srvhost, dbconn, debug, defaultShutdownTime, skt, nil)
srv := treemanager.NewServer(
tl,
dbconn,
treemanager.WithListen(srvhost),
treemanager.WithDebug(debug),
treemanager.WithShutdownTimeout(defaultShutdownTime),
treemanager.WithUnix(skt),
)

defer func() {
err := srv.Shutdown()
Expand Down
10 changes: 9 additions & 1 deletion tests/integration/helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,15 @@ func newTestServerWithNotifier(t *testing.T, skt string, notif notifier.Notifier

gooseDBMutex.Unlock()

tm := treemanager.NewServer(tl, srvhost, dbconn, debug, defaultShutdownTime, skt, notif)
tm := treemanager.NewServer(
tl,
dbconn,
treemanager.WithListen(srvhost),
treemanager.WithDebug(debug),
treemanager.WithShutdownTimeout(defaultShutdownTime),
treemanager.WithUnix(skt),
treemanager.WithNotifier(notif),
)

return tm
}
Expand Down