From e877ac3e616d453dce85df19047da3d52617b86f Mon Sep 17 00:00:00 2001 From: Garet Halliday <me@garet.holiday> Date: Mon, 16 Oct 2023 15:28:30 -0500 Subject: [PATCH] a --- cmd/pggat/pgbouncer.go | 3 +- lib/gat/app.go | 5 +- lib/gat/gatcaddyfile/gattype.go | 5 +- lib/gat/gatcaddyfile/handler.go | 5 +- lib/gat/gatcaddyfile/pooler.go | 14 +++-- lib/gat/handlers/discovery/config.go | 5 +- lib/gat/handlers/pgbouncer/module.go | 3 +- lib/gat/handlers/pool/pools/basic/config.go | 61 ++++++++++++++++++++ lib/gat/handlers/pool/pools/basic/factory.go | 40 +++++++++++++ lib/gat/handlers/pool/pools/basic/pool.go | 49 ++++++++++++++++ lib/util/dur/duration.go | 32 ---------- 11 files changed, 169 insertions(+), 53 deletions(-) create mode 100644 lib/gat/handlers/pool/pools/basic/config.go create mode 100644 lib/gat/handlers/pool/pools/basic/factory.go create mode 100644 lib/gat/handlers/pool/pools/basic/pool.go delete mode 100644 lib/util/dur/duration.go diff --git a/cmd/pggat/pgbouncer.go b/cmd/pggat/pgbouncer.go index 52dcf980..f6974738 100644 --- a/cmd/pggat/pgbouncer.go +++ b/cmd/pggat/pgbouncer.go @@ -11,7 +11,6 @@ import ( "gfx.cafe/gfx/pggat/lib/gat" "gfx.cafe/gfx/pggat/lib/gat/handlers/pgbouncer" - "gfx.cafe/gfx/pggat/lib/util/dur" ) func init() { @@ -37,7 +36,7 @@ func runPgbouncer(flags caddycmd.Flags) (int, error) { } var pggat gat.Config - pggat.StatLogPeriod = dur.Duration(time.Second) + pggat.StatLogPeriod = caddy.Duration(time.Second) var server gat.ServerConfig server.Listen = config.Listen() diff --git a/lib/gat/app.go b/lib/gat/app.go index 2bb1a58f..b9126960 100644 --- a/lib/gat/app.go +++ b/lib/gat/app.go @@ -7,11 +7,10 @@ import ( "go.uber.org/zap" "gfx.cafe/gfx/pggat/lib/gat/metrics" - "gfx.cafe/gfx/pggat/lib/util/dur" ) type Config struct { - StatLogPeriod dur.Duration `json:"stat_log_period,omitempty"` + StatLogPeriod caddy.Duration `json:"stat_log_period,omitempty"` Servers []ServerConfig `json:"servers,omitempty"` } @@ -56,7 +55,7 @@ func (T *App) Provision(ctx caddy.Context) error { } func (T *App) statLogLoop() { - t := time.NewTicker(T.StatLogPeriod.Duration()) + t := time.NewTicker(time.Duration(T.StatLogPeriod)) defer t.Stop() var stats metrics.Server diff --git a/lib/gat/gatcaddyfile/gattype.go b/lib/gat/gatcaddyfile/gattype.go index c1eb3ea8..6e2e5073 100644 --- a/lib/gat/gatcaddyfile/gattype.go +++ b/lib/gat/gatcaddyfile/gattype.go @@ -12,7 +12,6 @@ import ( "gfx.cafe/gfx/pggat/lib/gat" "gfx.cafe/gfx/pggat/lib/gat/matchers" "gfx.cafe/gfx/pggat/lib/gat/ssl/servers/self_signed" - "gfx.cafe/gfx/pggat/lib/util/dur" ) func init() { @@ -27,7 +26,7 @@ func (ServerType) Setup(blocks []caddyfile.ServerBlock, m map[string]any) (*cadd app := gat.App{ Config: gat.Config{ - StatLogPeriod: dur.Duration(1 * time.Minute), + StatLogPeriod: caddy.Duration(1 * time.Minute), }, } @@ -51,7 +50,7 @@ func (ServerType) Setup(blocks []caddyfile.ServerBlock, m map[string]any) (*cadd return nil, nil, d.WrapErr(err) } - app.StatLogPeriod = dur.Duration(period) + app.StatLogPeriod = caddy.Duration(period) default: return nil, nil, d.SyntaxErr("global options") } diff --git a/lib/gat/gatcaddyfile/handler.go b/lib/gat/gatcaddyfile/handler.go index 27b31788..06649368 100644 --- a/lib/gat/gatcaddyfile/handler.go +++ b/lib/gat/gatcaddyfile/handler.go @@ -24,7 +24,6 @@ import ( "gfx.cafe/gfx/pggat/lib/gat/handlers/rewrite_password" "gfx.cafe/gfx/pggat/lib/gat/handlers/rewrite_user" "gfx.cafe/gfx/pggat/lib/gat/ssl/clients/insecure_skip_verify" - "gfx.cafe/gfx/pggat/lib/util/dur" "gfx.cafe/gfx/pggat/lib/util/strutil" ) @@ -132,7 +131,7 @@ func init() { RegisterDirective(Handler, "discovery", func(d *caddyfile.Dispenser, warnings *[]caddyconfig.Warning) (caddy.Module, error) { module := discovery.Module{ Config: discovery.Config{ - ReconcilePeriod: dur.Duration(5 * time.Minute), + ReconcilePeriod: caddy.Duration(5 * time.Minute), Pooler: JSONModuleObject( &rob.Factory{ ManagementConfig: defaultPoolManagementConfig, @@ -185,7 +184,7 @@ func init() { if err != nil { return nil, d.WrapErr(err) } - module.ReconcilePeriod = dur.Duration(val) + module.ReconcilePeriod = caddy.Duration(val) case "discoverer": if !d.NextArg() { return nil, d.ArgErr() diff --git a/lib/gat/gatcaddyfile/pooler.go b/lib/gat/gatcaddyfile/pooler.go index bbaad5b9..b7f5bae8 100644 --- a/lib/gat/gatcaddyfile/pooler.go +++ b/lib/gat/gatcaddyfile/pooler.go @@ -9,13 +9,15 @@ import ( "gfx.cafe/gfx/pggat/lib/gat/pool" "gfx.cafe/gfx/pggat/lib/util/dur" + + "gfx.cafe/gfx/pggat/lib/gat/handlers/pool/poolers/lifo" "gfx.cafe/gfx/pggat/lib/util/strutil" ) var defaultPoolManagementConfig = pool.ManagementConfig{ - ServerIdleTimeout: dur.Duration(5 * time.Minute), - ServerReconnectInitialTime: dur.Duration(5 * time.Second), - ServerReconnectMaxTime: dur.Duration(1 * time.Minute), + ServerIdleTimeout: caddy.Duration(5 * time.Minute), + ServerReconnectInitialTime: caddy.Duration(5 * time.Second), + ServerReconnectMaxTime: caddy.Duration(1 * time.Minute), TrackedParameters: []strutil.CIString{ strutil.MakeCIString("client_encoding"), strutil.MakeCIString("datestyle"), @@ -50,7 +52,7 @@ func unmarshalPoolConfig(d *caddyfile.Dispenser) (pool.ManagementConfig, error) if err != nil { return config, d.WrapErr(err) } - config.ServerIdleTimeout = dur.Duration(val) + config.ServerIdleTimeout = caddy.Duration(val) case "reconnect": if !d.NextArg() { return config, d.ArgErr() @@ -69,8 +71,8 @@ func unmarshalPoolConfig(d *caddyfile.Dispenser) (pool.ManagementConfig, error) } } - config.ServerReconnectInitialTime = dur.Duration(initialTime) - config.ServerReconnectMaxTime = dur.Duration(maxTime) + config.ServerReconnectInitialTime = caddy.Duration(initialTime) + config.ServerReconnectMaxTime = caddy.Duration(maxTime) case "track": if !d.NextArg() { return config, d.ArgErr() diff --git a/lib/gat/handlers/discovery/config.go b/lib/gat/handlers/discovery/config.go index a8ff6304..056fa5a5 100644 --- a/lib/gat/handlers/discovery/config.go +++ b/lib/gat/handlers/discovery/config.go @@ -3,13 +3,14 @@ package discovery import ( "encoding/json" + "github.com/caddyserver/caddy/v2" + "gfx.cafe/gfx/pggat/lib/bouncer" - "gfx.cafe/gfx/pggat/lib/util/dur" ) type Config struct { // ReconcilePeriod is how often the module should check for changes. 0 = disable - ReconcilePeriod dur.Duration `json:"reconcile_period"` + ReconcilePeriod caddy.Duration `json:"reconcile_period"` Discoverer json.RawMessage `json:"discoverer" caddy:"namespace=pggat.handlers.discovery.discoverers inline_key=discoverer"` diff --git a/lib/gat/handlers/pgbouncer/module.go b/lib/gat/handlers/pgbouncer/module.go index 36ba561e..0861af93 100644 --- a/lib/gat/handlers/pgbouncer/module.go +++ b/lib/gat/handlers/pgbouncer/module.go @@ -19,7 +19,6 @@ import ( "gfx.cafe/gfx/pggat/lib/fed" "gfx.cafe/gfx/pggat/lib/gat/handlers/pool" "gfx.cafe/gfx/pggat/lib/perror" - "gfx.cafe/gfx/pggat/lib/util/dur" "gfx.cafe/gfx/pggat/lib/util/flip" "gfx.cafe/gfx/pggat/lib/util/slices" @@ -187,7 +186,7 @@ func (T *Module) tryCreate(user, database string) (poolAndCredentials, bool) { strutil.MakeCIString("application_name"), }, T.Config.PgBouncer.TrackExtraParameters...) - serverLoginRetry := dur.Duration(T.Config.PgBouncer.ServerLoginRetry * float64(time.Second)) + serverLoginRetry := caddy.Duration(T.Config.PgBouncer.ServerLoginRetry * float64(time.Second)) var p poolAndCredentials p.creds = creds diff --git a/lib/gat/handlers/pool/pools/basic/config.go b/lib/gat/handlers/pool/pools/basic/config.go new file mode 100644 index 00000000..493159d9 --- /dev/null +++ b/lib/gat/handlers/pool/pools/basic/config.go @@ -0,0 +1,61 @@ +package basic + +import ( + "encoding/json" + + "github.com/caddyserver/caddy/v2" + "go.uber.org/zap" + + "gfx.cafe/gfx/pggat/lib/gat/handlers/pool" + "gfx.cafe/gfx/pggat/lib/util/strutil" +) + +type ParameterStatusSync string + +const ( + // ParameterStatusSyncNone does not attempt to sync parameter status. + ParameterStatusSyncNone ParameterStatusSync = "" + // ParameterStatusSyncInitial assumes both client and server have their initial status before syncing. + // Use in session pooling for lower latency + ParameterStatusSyncInitial = "initial" + // ParameterStatusSyncDynamic will track parameter status and ensure they are synced correctly. + // Use in transaction pooling + ParameterStatusSyncDynamic = "dynamic" +) + +type Config struct { + RawPoolerFactory json.RawMessage `json:"pooler" caddy:"namespace=pggat.handlers.pool.poolers inline_key=pooler"` + + PoolerFactory pool.PoolerFactory `json:"-"` + + // ReleaseAfterTransaction toggles whether servers should be released and re acquired after each transaction. + // Use false for lower latency + // Use true for better balancing + ReleaseAfterTransaction bool `json:"release_after_transaction,omitempty"` + + // ParameterStatusSync is the parameter syncing mode + ParameterStatusSync ParameterStatusSync `json:"parameter_status_sync,omitempty"` + + // ExtendedQuerySync controls whether prepared statements and portals should be tracked and synced before use. + // Use false for lower latency + // Use true for transaction pooling + ExtendedQuerySync bool `json:"extended_query_sync,omitempty"` + + ServerResetQuery string `json:"server_reset_query,omitempty"` + + // ServerIdleTimeout defines how long a server may be idle before it is disconnected + ServerIdleTimeout caddy.Duration `json:"server_idle_timeout,omitempty"` + + // ServerReconnectInitialTime defines how long to wait initially before attempting a server reconnect + // 0 = disable, don't retry + ServerReconnectInitialTime caddy.Duration `json:"server_reconnect_initial_time,omitempty"` + + // ServerReconnectMaxTime defines the max amount of time to wait before attempting a server reconnect + // 0 = disable, back off infinitely + ServerReconnectMaxTime caddy.Duration `json:"server_reconnect_max_time,omitempty"` + + // TrackedParameters are parameters which should be synced by updating the server, not the client. + TrackedParameters []strutil.CIString `json:"tracked_parameters,omitempty"` + + Logger *zap.Logger `json:"-"` +} diff --git a/lib/gat/handlers/pool/pools/basic/factory.go b/lib/gat/handlers/pool/pools/basic/factory.go new file mode 100644 index 00000000..2c03827a --- /dev/null +++ b/lib/gat/handlers/pool/pools/basic/factory.go @@ -0,0 +1,40 @@ +package basic + +import ( + "github.com/caddyserver/caddy/v2" + + "gfx.cafe/gfx/pggat/lib/gat/handlers/pool" +) + +type Factory struct { + Config +} + +func (T *Factory) CaddyModule() caddy.ModuleInfo { + return caddy.ModuleInfo{ + ID: "pggat.handlers.pool.pools.basic", + New: func() caddy.Module { + return new(Factory) + }, + } +} + +func (T *Factory) Provision(ctx caddy.Context) error { + T.Logger = ctx.Logger() + + raw, err := ctx.LoadModule(T, "RawPoolerFactory") + if err != nil { + return err + } + + T.PoolerFactory = raw.(pool.PoolerFactory) + return nil +} + +func (T *Factory) NewPool() pool.Pool { + return NewPool(T.Config) +} + +var _ pool.PoolFactory = (*Factory)(nil) +var _ caddy.Module = (*Factory)(nil) +var _ caddy.Provisioner = (*Factory)(nil) diff --git a/lib/gat/handlers/pool/pools/basic/pool.go b/lib/gat/handlers/pool/pools/basic/pool.go new file mode 100644 index 00000000..fde1ae0d --- /dev/null +++ b/lib/gat/handlers/pool/pools/basic/pool.go @@ -0,0 +1,49 @@ +package basic + +import ( + "gfx.cafe/gfx/pggat/lib/fed" + "gfx.cafe/gfx/pggat/lib/gat/handlers/pool" + "gfx.cafe/gfx/pggat/lib/gat/metrics" +) + +type Pool struct { + config Config +} + +func NewPool(config Config) *Pool { + return &Pool{ + config: config, + } +} + +func (T *Pool) AddRecipe(name string, recipe *pool.Recipe) { + // TODO implement me + panic("implement me") +} + +func (T *Pool) RemoveRecipe(name string) { + // TODO implement me + panic("implement me") +} + +func (T *Pool) Serve(conn *fed.Conn) error { + // TODO implement me + panic("implement me") +} + +func (T *Pool) Cancel(key fed.BackendKey) { + // TODO implement me + panic("implement me") +} + +func (T *Pool) ReadMetrics(m *metrics.Pool) { + // TODO implement me + panic("implement me") +} + +func (T *Pool) Close() { + // TODO implement me + panic("implement me") +} + +var _ pool.Pool = (*Pool)(nil) diff --git a/lib/util/dur/duration.go b/lib/util/dur/duration.go deleted file mode 100644 index b2847c62..00000000 --- a/lib/util/dur/duration.go +++ /dev/null @@ -1,32 +0,0 @@ -package dur - -import ( - "encoding/json" - "time" -) - -type Duration time.Duration - -func (T *Duration) Duration() time.Duration { - return time.Duration(*T) -} - -func (T *Duration) UnmarshalJSON(bytes []byte) error { - // try as string - var str string - if err := json.Unmarshal(bytes, &str); err == nil { - *(*time.Duration)(T), err = time.ParseDuration(str) - return err - } - - // try num - var num int64 - if err := json.Unmarshal(bytes, &num); err != nil { - return err - } - *T = Duration(num) - - return nil -} - -var _ json.Unmarshaler = (*Duration)(nil) -- GitLab