Skip to content

Commit

Permalink
support both config object (for cobra bindings) and functional options
Browse files Browse the repository at this point in the history
for datastore
  • Loading branch information
ecordell committed Dec 7, 2021
1 parent 3dbe72f commit 1783cec
Show file tree
Hide file tree
Showing 8 changed files with 229 additions and 203 deletions.
1 change: 1 addition & 0 deletions .github/workflows/lint.yaml
Expand Up @@ -20,6 +20,7 @@ jobs:
# This is done before checking out, as to not modify go.mod
go install mvdan.cc/gofumpt/gofumports@v0.1.1
go install golang.org/x/tools/cmd/stringer@latest
go install github.com/ecordell/optgen@v0.0.4
- uses: "actions/checkout@v2"
- name: "Go Mod Tidy"
run: "go mod tidy && bash -c '[ $(git status --porcelain | tee /dev/fd/2 | wc -c) -eq 0 ]'"
Expand Down
31 changes: 7 additions & 24 deletions cmd/spicedb/serve.go
Expand Up @@ -22,7 +22,6 @@ import (

"github.com/authzed/spicedb/internal/auth"
"github.com/authzed/spicedb/internal/dashboard"
"github.com/authzed/spicedb/internal/datastore"
"github.com/authzed/spicedb/internal/datastore/proxy"
combineddispatch "github.com/authzed/spicedb/internal/dispatch/combined"
"github.com/authzed/spicedb/internal/gateway"
Expand All @@ -37,12 +36,15 @@ import (
)

func registerServeCmd(rootCmd *cobra.Command) {
var datastoreOptions serve.DatastoreConfig
serveCmd := &cobra.Command{
Use: "serve",
Short: "serve the permissions database",
Long: "A database that stores, computes, and validates application permissions",
PreRunE: defaultPreRunE,
Run: serveRun,
Run: func(cmd *cobra.Command, args []string) {
serveRun(cmd, args, datastoreOptions)
},
Example: fmt.Sprintf(` %s:
spicedb serve --grpc-preshared-key "somerandomkeyhere"
Expand All @@ -62,7 +64,6 @@ func registerServeCmd(rootCmd *cobra.Command) {
}

// Flags for the datastore
var datastoreOptions serve.Options
serve.RegisterDatastoreFlags(serveCmd, &datastoreOptions)
serveCmd.Flags().Bool("datastore-readonly", false, "set the service to read-only mode")
serveCmd.Flags().StringSlice("datastore-bootstrap-files", []string{}, "bootstrap data yaml files to load")
Expand Down Expand Up @@ -102,31 +103,13 @@ func registerServeCmd(rootCmd *cobra.Command) {
rootCmd.AddCommand(serveCmd)
}

func serveRun(cmd *cobra.Command, args []string) {
func serveRun(cmd *cobra.Command, args []string, datastoreOpts serve.DatastoreConfig) {
token := cobrautil.MustGetStringExpanded(cmd, "grpc-preshared-key")
if len(token) < 1 {
log.Fatal().Msg("a preshared key must be provided via --grpc-preshared-key to authenticate API requests")
}

datastoreEngine := cobrautil.MustGetStringExpanded(cmd, "datastore-engine")
ds, err := serve.NewDatastore(
datastore.Engine(datastoreEngine),
serve.WithRevisionQuantization(cobrautil.MustGetDuration(cmd, "datastore-revision-fuzzing-duration")),
serve.WithGCWindow(cobrautil.MustGetDuration(cmd, "datastore-gc-window")),
serve.WithURI(cobrautil.MustGetStringExpanded(cmd, "datastore-conn-uri")),
serve.WithMaxIdleTime(cobrautil.MustGetDuration(cmd, "datastore-conn-max-idletime")),
serve.WithMaxLifetime(cobrautil.MustGetDuration(cmd, "datastore-conn-max-lifetime")),
serve.WithMaxOpenConns(cobrautil.MustGetInt(cmd, "datastore-conn-max-open")),
serve.WithMinOpenConns(cobrautil.MustGetInt(cmd, "datastore-conn-min-open")),
serve.WithSplitQuerySize(cobrautil.MustGetStringExpanded(cmd, "datastore-query-split-size")),
serve.WithFollowerReadDelay(cobrautil.MustGetDuration(cmd, "datastore-follower-read-delay-duration")),
serve.WithMaxRetries(cobrautil.MustGetInt(cmd, "datastore-max-tx-retries")),
serve.WithOverlapKey(cobrautil.MustGetStringExpanded(cmd, "datastore-tx-overlap-key")),
serve.WithOverlapStrategy(cobrautil.MustGetStringExpanded(cmd, "datastore-tx-overlap-strategy")),
serve.WithHealthCheckPeriod(cobrautil.MustGetDuration(cmd, "datastore-conn-healthcheck-interval")),
serve.WithGCInterval(cobrautil.MustGetDuration(cmd, "datastore-gc-interval")),
serve.WithGCMaxOperationTime(cobrautil.MustGetDuration(cmd, "datastore-gc-max-operation-time")),
)
ds, err := serve.NewDatastore(datastoreOpts.ToOption())
if err != nil {
log.Fatal().Err(err).Msg("failed to init datastore")
}
Expand Down Expand Up @@ -288,7 +271,7 @@ func serveRun(cmd *cobra.Command, args []string) {
dashboardSrv.Handler = dashboard.NewHandler(
cobrautil.MustGetStringExpanded(cmd, "grpc-addr"),
cobrautil.MustGetStringExpanded(cmd, "grpc-tls-cert-path") != "" && cobrautil.MustGetStringExpanded(cmd, "grpc-tls-key-path") != "",
datastoreEngine,
datastoreOpts.Engine,
ds,
)
go func() {
Expand Down
28 changes: 0 additions & 28 deletions internal/datastore/crdb/crdb.go
Expand Up @@ -18,7 +18,6 @@ import (

"github.com/authzed/spicedb/internal/datastore"
"github.com/authzed/spicedb/internal/datastore/crdb/migrations"
"github.com/authzed/spicedb/pkg/cmd/serve"
)

var (
Expand Down Expand Up @@ -50,35 +49,8 @@ const (
querySelectNow = "SELECT cluster_logical_timestamp()"
queryReturningTimestamp = "RETURNING cluster_logical_timestamp()"
queryShowZoneConfig = "SHOW ZONE CONFIGURATION FOR RANGE default;"

cockroachEngine datastore.Engine = "cockroach"
)

func init() {
serve.RegisterEngine(cockroachEngine, newFromDatastoreOptions)
}

func newFromDatastoreOptions(opts serve.Options) (datastore.Datastore, error) {
splitQuerySize, err := units.ParseBase2Bytes(opts.SplitQuerySize)
if err != nil {
return nil, fmt.Errorf("failed to parse split query size: %w", err)
}
return NewCRDBDatastore(
opts.URI,
GCWindow(opts.GCWindow),
RevisionQuantization(opts.RevisionQuantization),
ConnMaxIdleTime(opts.MaxIdleTime),
ConnMaxLifetime(opts.MaxLifetime),
MaxOpenConns(opts.MaxOpenConns),
MinOpenConns(opts.MinOpenConns),
SplitAtEstimatedQuerySize(splitQuerySize),
FollowerReadDelay(opts.FollowerReadDelay),
MaxRetries(opts.MaxRetries),
OverlapKey(opts.OverlapKey),
OverlapStrategy(opts.OverlapStrategy),
)
}

// NewCRDBDatastore initializes a SpiceDB datastore that uses a CockroachDB
// database while leveraging its AOST functionality.
func NewCRDBDatastore(url string, options ...Option) (datastore.Datastore, error) {
Expand Down
3 changes: 0 additions & 3 deletions internal/datastore/datastore.go
Expand Up @@ -150,6 +150,3 @@ type Revision = decimal.Decimal
// revision type in the future a bit easier if necessary. Implementations
// should use any time they want to signal an empty/error revision.
var NoRevision Revision

// Engine represents the type of a datastore engine, i.e. Cockroach or Postgres
type Engine string
13 changes: 0 additions & 13 deletions internal/datastore/memdb/memdb.go
Expand Up @@ -11,24 +11,11 @@ import (
v1 "github.com/authzed/authzed-go/proto/authzed/api/v1"
"github.com/hashicorp/go-memdb"
"github.com/jzelinskie/stringz"
"github.com/rs/zerolog/log"
"github.com/shopspring/decimal"

"github.com/authzed/spicedb/internal/datastore"
"github.com/authzed/spicedb/pkg/cmd/serve"
)

const memoryEngine datastore.Engine = "memory"

func init() {
serve.RegisterEngine(memoryEngine, newFromDatastoreOptions)
}

func newFromDatastoreOptions(opts serve.Options) (datastore.Datastore, error) {
log.Warn().Msg("in-memory datastore is not persistent and not feasible to run in a high availability fashion")
return NewMemdbDatastore(0, opts.RevisionQuantization, opts.GCWindow, 0)
}

// DisableGC is a convenient constant for setting the garbage collection
// interval high enough that it will never run.
const DisableGC = time.Duration(math.MaxInt64)
Expand Down
26 changes: 0 additions & 26 deletions internal/datastore/postgres/postgres.go
Expand Up @@ -24,7 +24,6 @@ import (

"github.com/authzed/spicedb/internal/datastore"
"github.com/authzed/spicedb/internal/datastore/postgres/migrations"
"github.com/authzed/spicedb/pkg/cmd/serve"
)

const (
Expand Down Expand Up @@ -56,8 +55,6 @@ const (
tracingDriverName = "postgres-tracing"

batchDeleteSize = 1000

postgresEngine datastore.Engine = "postgres"
)

var (
Expand Down Expand Up @@ -86,29 +83,6 @@ var (

func init() {
dbsql.Register(tracingDriverName, sqlmw.Driver(stdlib.GetDefaultDriver(), new(traceInterceptor)))
serve.RegisterEngine(postgresEngine, newFromDatastoreOptions)
}

func newFromDatastoreOptions(opts serve.Options) (datastore.Datastore, error) {
splitQuerySize, err := units.ParseBase2Bytes(opts.SplitQuerySize)
if err != nil {
return nil, fmt.Errorf("failed to parse split query size: %w", err)
}
return NewPostgresDatastore(
opts.URI,
GCWindow(opts.GCWindow),
RevisionFuzzingTimedelta(opts.RevisionQuantization),
ConnMaxIdleTime(opts.MaxIdleTime),
ConnMaxLifetime(opts.MaxLifetime),
MaxOpenConns(opts.MaxOpenConns),
MinOpenConns(opts.MinOpenConns),
SplitAtEstimatedQuerySize(splitQuerySize),
HealthCheckPeriod(opts.HealthCheckPeriod),
GCInterval(opts.GCInterval),
GCMaxOperationTime(opts.GCMaxOperationTime),
EnablePrometheusStats(),
EnableTracing(),
)
}

var (
Expand Down

0 comments on commit 1783cec

Please sign in to comment.