From 5b0d733209a06cbc1315a3d679947c4db449be31 Mon Sep 17 00:00:00 2001 From: Jacob LeGrone Date: Fri, 10 Mar 2023 16:34:22 -0500 Subject: [PATCH] Avoid stuttering in temporalite package --- temporal/temporalite/config.go | 26 +++----------- temporal/temporalite/options.go | 61 ++++++++++++++++++++++++--------- temporal/temporalite/server.go | 24 ++++++------- temporal/temporaltest/server.go | 2 +- 4 files changed, 62 insertions(+), 51 deletions(-) diff --git a/temporal/temporalite/config.go b/temporal/temporalite/config.go index f052f5e858db..b3269bdb5b68 100644 --- a/temporal/temporalite/config.go +++ b/temporal/temporalite/config.go @@ -15,11 +15,9 @@ import ( "go.temporal.io/server/common/cluster" "go.temporal.io/server/common/config" - "go.temporal.io/server/common/dynamicconfig" "go.temporal.io/server/common/log" "go.temporal.io/server/common/metrics" "go.temporal.io/server/common/persistence/sql/sqlplugin/sqlite" - "go.temporal.io/server/temporal" ) const ( @@ -27,22 +25,6 @@ const ( defaultFrontendPort = 7233 ) -type liteConfig struct { - Ephemeral bool - DatabaseFilePath string - FrontendPort int - MetricsPort int - DynamicPorts bool - Namespaces []string - SQLitePragmas map[string]string - Logger log.Logger - ServerOptions []temporal.ServerOption - portProvider *portProvider - FrontendIP string - BaseConfig *config.Config - DynamicConfig dynamicconfig.StaticClient -} - var supportedPragmas = map[string]struct{}{ "journal_mode": {}, "synchronous": {}, @@ -57,13 +39,13 @@ func getAllowedPragmas() []string { return allowedPragmaList } -func newDefaultConfig() (*liteConfig, error) { +func newDefaultConfig() (*temporaliteConfig, error) { userConfigDir, err := os.UserConfigDir() if err != nil { return nil, fmt.Errorf("cannot determine user config directory: %w", err) } - return &liteConfig{ + return &temporaliteConfig{ Ephemeral: false, DatabaseFilePath: filepath.Join(userConfigDir, "temporalite", "db", "default.db"), FrontendPort: 0, @@ -82,7 +64,7 @@ func newDefaultConfig() (*liteConfig, error) { }, nil } -func convertLiteConfig(cfg *liteConfig) *config.Config { +func convertLiteConfig(cfg *temporaliteConfig) *config.Config { defer func() { if err := cfg.portProvider.Close(); err != nil { panic(err) @@ -196,7 +178,7 @@ func convertLiteConfig(cfg *liteConfig) *config.Config { return baseConfig } -func (cfg *liteConfig) mustGetService(frontendPortOffset int) config.Service { +func (cfg *temporaliteConfig) mustGetService(frontendPortOffset int) config.Service { svc := config.Service{ RPC: config.RPC{ GRPCPort: cfg.FrontendPort + frontendPortOffset, diff --git a/temporal/temporalite/options.go b/temporal/temporalite/options.go index 7819d904e382..6ec92dd142a7 100644 --- a/temporal/temporalite/options.go +++ b/temporal/temporalite/options.go @@ -11,16 +11,45 @@ import ( "go.temporal.io/server/temporal" ) +type temporaliteConfig struct { + // When true, Ephemeral disables file persistence and uses the in-memory storage driver. + // State will be reset on each process restart. + Ephemeral bool + // DatabaseFilePath persists state to the file at the specified path. + // + // This is required if Ephemeral is false. + DatabaseFilePath string + FrontendPort int + // WithMetricsPort sets the listening port for metrics. + // + // When unspecified, the port will be system-chosen. + MetricsPort int + DynamicPorts bool + Namespaces []string + SQLitePragmas map[string]string + // Logger overrides the default logger. + Logger log.Logger + ServerOptions []temporal.ServerOption + portProvider *portProvider + FrontendIP string + // BaseConfig sets the default Temporal server configuration. + // + // Storage and client configuration will always be overridden, however base config can be + // used to enable settings like TLS or authentication. + BaseConfig *config.Config + DynamicConfig dynamicconfig.StaticClient +} + // WithLogger overrides the default logger. func WithLogger(logger log.Logger) ServerOption { - return newApplyFuncContainer(func(cfg *liteConfig) { + return newApplyFuncContainer(func(cfg *temporaliteConfig) { cfg.Logger = logger }) } // WithDatabaseFilePath persists state to the file at the specified path. func WithDatabaseFilePath(filepath string) ServerOption { - return newApplyFuncContainer(func(cfg *liteConfig) { + return newApplyFuncContainer(func(cfg *temporaliteConfig) { cfg.Ephemeral = false cfg.DatabaseFilePath = filepath }) @@ -29,7 +58,7 @@ func WithDatabaseFilePath(filepath string) ServerOption { // WithPersistenceDisabled disables file persistence and uses the in-memory storage driver. // State will be reset on each process restart. func WithPersistenceDisabled() ServerOption { - return newApplyFuncContainer(func(cfg *liteConfig) { + return newApplyFuncContainer(func(cfg *temporaliteConfig) { cfg.Ephemeral = true }) } @@ -38,7 +67,7 @@ func WithPersistenceDisabled() ServerOption { // // When unspecified, the default port number of 7233 is used. func WithFrontendPort(port int) ServerOption { - return newApplyFuncContainer(func(cfg *liteConfig) { + return newApplyFuncContainer(func(cfg *temporaliteConfig) { cfg.FrontendPort = port }) } @@ -47,7 +76,7 @@ func WithFrontendPort(port int) ServerOption { // // When unspecified, the port will be system-chosen. func WithMetricsPort(port int) ServerOption { - return newApplyFuncContainer(func(cfg *liteConfig) { + return newApplyFuncContainer(func(cfg *temporaliteConfig) { cfg.MetricsPort = port }) } @@ -57,28 +86,28 @@ func WithMetricsPort(port int) ServerOption { // // When unspecified, the frontend service will bind to localhost. func WithFrontendIP(address string) ServerOption { - return newApplyFuncContainer(func(cfg *liteConfig) { + return newApplyFuncContainer(func(cfg *temporaliteConfig) { cfg.FrontendIP = address }) } // WithDynamicPorts starts Temporal on system-chosen ports. -func WithDynamicPorts() ServerOption { - return newApplyFuncContainer(func(cfg *liteConfig) { +func WithDynamicPorts() Option { + return newApplyFuncContainer(func(cfg *temporaliteConfig) { cfg.DynamicPorts = true }) } // WithNamespaces registers each namespace on Temporal start. func WithNamespaces(namespaces ...string) ServerOption { - return newApplyFuncContainer(func(cfg *liteConfig) { + return newApplyFuncContainer(func(cfg *temporaliteConfig) { cfg.Namespaces = append(cfg.Namespaces, namespaces...) }) } // WithSQLitePragmas applies pragma statements to SQLite on Temporal start. func WithSQLitePragmas(pragmas map[string]string) ServerOption { - return newApplyFuncContainer(func(cfg *liteConfig) { + return newApplyFuncContainer(func(cfg *temporaliteConfig) { if cfg.SQLitePragmas == nil { cfg.SQLitePragmas = make(map[string]string) } @@ -90,7 +119,7 @@ func WithSQLitePragmas(pragmas map[string]string) ServerOption { // WithOptions registers Temporal server options. func WithOptions(options ...temporal.ServerOption) ServerOption { - return newApplyFuncContainer(func(cfg *liteConfig) { + return newApplyFuncContainer(func(cfg *temporaliteConfig) { cfg.ServerOptions = append(cfg.ServerOptions, options...) }) } @@ -100,7 +129,7 @@ func WithOptions(options ...temporal.ServerOption) ServerOption { // Storage and client configuration will always be overridden, however base config can be // used to enable settings like TLS or authentication. func WithBaseConfig(base *config.Config) ServerOption { - return newApplyFuncContainer(func(cfg *liteConfig) { + return newApplyFuncContainer(func(cfg *temporaliteConfig) { cfg.BaseConfig = base }) } @@ -108,7 +137,7 @@ func WithBaseConfig(base *config.Config) ServerOption { // WithDynamicConfigValue sets the given dynamic config key with the given set // of values. This will overwrite a key if already set. func WithDynamicConfigValue(key dynamicconfig.Key, value []dynamicconfig.ConstrainedValue) ServerOption { - return newApplyFuncContainer(func(cfg *liteConfig) { + return newApplyFuncContainer(func(cfg *temporaliteConfig) { if cfg.DynamicConfig == nil { cfg.DynamicConfig = dynamicconfig.StaticClient{} } @@ -128,14 +157,14 @@ func WithSearchAttributeCacheDisabled() ServerOption { } type applyFuncContainer struct { - applyInternal func(*liteConfig) + applyInternal func(*temporaliteConfig) } -func (fso *applyFuncContainer) apply(cfg *liteConfig) { +func (fso *applyFuncContainer) apply(cfg *temporaliteConfig) { fso.applyInternal(cfg) } -func newApplyFuncContainer(apply func(*liteConfig)) *applyFuncContainer { +func newApplyFuncContainer(apply func(*temporaliteConfig)) *applyFuncContainer { return &applyFuncContainer{ applyInternal: apply, } diff --git a/temporal/temporalite/server.go b/temporal/temporalite/server.go index fba1a18f43b2..d17934ed4aca 100644 --- a/temporal/temporalite/server.go +++ b/temporal/temporalite/server.go @@ -21,19 +21,19 @@ import ( "go.temporal.io/server/temporal" ) -// TemporaliteServer is a high level wrapper for temporal.Server that automatically configures a sqlite backend. -type TemporaliteServer struct { +// Server is a high level wrapper for temporal.Server that automatically configures a sqlite backend. +type Server struct { internal temporal.Server frontendHostPort string - config *liteConfig + config *temporaliteConfig } type ServerOption interface { - apply(*liteConfig) + apply(*temporaliteConfig) } -// NewServer returns a TemporaliteServer with a sqlite backend. -func NewServer(opts ...ServerOption) (*TemporaliteServer, error) { +// NewServer returns a Server with a sqlite backend. +func NewServer(opts ...ServerOption) (*Server, error) { c, err := newDefaultConfig() if err != nil { return nil, err @@ -112,7 +112,7 @@ func NewServer(opts ...ServerOption) (*TemporaliteServer, error) { return nil, fmt.Errorf("unable to instantiate server: %w", err) } - s := &TemporaliteServer{ + s := &Server{ internal: srv, frontendHostPort: cfg.PublicClient.HostPort, config: c, @@ -122,12 +122,12 @@ func NewServer(opts ...ServerOption) (*TemporaliteServer, error) { } // Start temporal server. -func (s *TemporaliteServer) Start() error { +func (s *Server) Start() error { return s.internal.Start() } // Stop the server. -func (s *TemporaliteServer) Stop() { +func (s *Server) Stop() { if s == nil { return } @@ -136,7 +136,7 @@ func (s *TemporaliteServer) Stop() { // NewClient initializes a client ready to communicate with the Temporal // server in the target namespace. -func (s *TemporaliteServer) NewClient(ctx context.Context, namespace string) (client.Client, error) { +func (s *Server) NewClient(ctx context.Context, namespace string) (client.Client, error) { return s.NewClientWithOptions(ctx, client.Options{Namespace: namespace}) } @@ -145,7 +145,7 @@ func (s *TemporaliteServer) NewClient(ctx context.Context, namespace string) (cl // To set the client's namespace, use the corresponding field in client.Options. // // Note that the HostPort and ConnectionOptions fields of client.Options will always be overridden. -func (s *TemporaliteServer) NewClientWithOptions(ctx context.Context, options client.Options) (client.Client, error) { +func (s *Server) NewClientWithOptions(ctx context.Context, options client.Options) (client.Client, error) { options.HostPort = s.frontendHostPort return client.NewClient(options) } @@ -154,6 +154,6 @@ func (s *TemporaliteServer) NewClientWithOptions(ctx context.Context, options cl // // When constructing a Temporalite client from within the same process, // NewClient or NewClientWithOptions should be used instead. -func (s *TemporaliteServer) FrontendHostPort() string { +func (s *Server) FrontendHostPort() string { return s.frontendHostPort } diff --git a/temporal/temporaltest/server.go b/temporal/temporaltest/server.go index 0f145dbd080f..4920bd8ccb21 100644 --- a/temporal/temporaltest/server.go +++ b/temporal/temporaltest/server.go @@ -24,7 +24,7 @@ import ( // A TestServer is a Temporal server listening on a system-chosen port on the // local loopback interface, for use in end-to-end tests. type TestServer struct { - server *temporalite.TemporaliteServer + server *temporalite.Server defaultTestNamespace string defaultClient client.Client clients []client.Client