Files
base/pkg/rabbit/config.go
2026-04-10 18:25:21 +03:30

226 lines
6.0 KiB
Go

package rabbitmq
import (
"fmt"
"net/url"
"time"
)
type Config struct {
// Connection settings
URL string `json:"url"`
Host string `json:"host"`
Port int `json:"port"`
Username string `json:"username"`
Password string `json:"password"`
VHost string `json:"vhost"`
UseTLS bool `json:"use_tls"`
// Connection pool settings
MaxConnections int `json:"max_connections"`
MaxChannels int `json:"max_channels"`
ConnectionTimeout time.Duration `json:"connection_timeout"`
HeartbeatInterval time.Duration `json:"heartbeat_interval"`
// Reconnection settings
ReconnectDelay time.Duration `json:"reconnect_delay"`
MaxReconnectDelay time.Duration `json:"max_reconnect_delay"`
ReconnectAttempts int `json:"reconnect_attempts"`
EnableAutoReconnect bool `json:"enable_auto_reconnect"`
// Publisher settings
PublisherConfig PublisherOptions `json:"publisher_config"`
// Health check settings
HealthCheckInterval time.Duration `json:"health_check_interval"`
}
func DefaultConfig() *Config {
return &Config{
Host: "localhost",
Port: 5672,
Username: "guest",
Password: "guest",
VHost: "/",
UseTLS: false,
MaxConnections: 10,
MaxChannels: 100,
ConnectionTimeout: 30 * time.Second,
HeartbeatInterval: 60 * time.Second,
ReconnectDelay: 5 * time.Second,
MaxReconnectDelay: 5 * time.Minute,
ReconnectAttempts: 10,
EnableAutoReconnect: true,
PublisherConfig: PublisherOptions{
ConfirmMode: true,
Mandatory: false,
Immediate: false,
RetryAttempts: 3,
RetryDelay: 1 * time.Second,
ConfirmTimeout: 10 * time.Second,
},
HealthCheckInterval: 30 * time.Second,
}
}
func (c *Config) BuildConnectionString() string {
if c.URL != "" {
return c.URL
}
scheme := "amqp"
if c.UseTLS {
scheme = "amqps"
}
// Build URL
u := &url.URL{
Scheme: scheme,
Host: fmt.Sprintf("%s:%d", c.Host, c.Port),
Path: c.VHost,
}
if c.Username != "" && c.Password != "" {
u.User = url.UserPassword(c.Username, c.Password)
}
return u.String()
}
func (c *Config) Validate() error {
if c.URL == "" {
if c.Host == "" {
return NewConfigurationError("host", c.Host, "host cannot be empty when URL is not provided")
}
if c.Port <= 0 || c.Port > 65535 {
return NewConfigurationError("port", c.Port, "port must be between 1 and 65535")
}
} else {
if _, err := url.Parse(c.URL); err != nil {
return NewConfigurationError("url", c.URL, fmt.Sprintf("invalid URL format: %v", err))
}
}
if c.MaxConnections <= 0 {
return NewConfigurationError("max_connections", c.MaxConnections, "max_connections must be greater than 0")
}
if c.MaxChannels <= 0 {
return NewConfigurationError("max_channels", c.MaxChannels, "max_channels must be greater than 0")
}
if c.ConnectionTimeout <= 0 {
return NewConfigurationError("connection_timeout", c.ConnectionTimeout, "connection_timeout must be greater than 0")
}
if c.HeartbeatInterval < 0 {
return NewConfigurationError("heartbeat_interval", c.HeartbeatInterval, "heartbeat_interval cannot be negative")
}
if c.ReconnectDelay <= 0 {
return NewConfigurationError("reconnect_delay", c.ReconnectDelay, "reconnect_delay must be greater than 0")
}
if c.MaxReconnectDelay < c.ReconnectDelay {
return NewConfigurationError("max_reconnect_delay", c.MaxReconnectDelay, "max_reconnect_delay must be greater than or equal to reconnect_delay")
}
if c.ReconnectAttempts < 0 {
return NewConfigurationError("reconnect_attempts", c.ReconnectAttempts, "reconnect_attempts cannot be negative")
}
if c.HealthCheckInterval < 0 {
return NewConfigurationError("health_check_interval", c.HealthCheckInterval, "health_check_interval cannot be negative")
}
return nil
}
func (c *Config) validatePublisherConfig() error {
if c.PublisherConfig.RetryAttempts < 0 {
return NewConfigurationError("publisher.retry_attempts", c.PublisherConfig.RetryAttempts, "retry_attempts cannot be negative")
}
if c.PublisherConfig.RetryDelay < 0 {
return NewConfigurationError("publisher.retry_delay", c.PublisherConfig.RetryDelay, "retry_delay cannot be negative")
}
if c.PublisherConfig.ConfirmTimeout <= 0 {
return NewConfigurationError("publisher.confirm_timeout", c.PublisherConfig.ConfirmTimeout, "confirm_timeout must be greater than 0")
}
return nil
}
func (c *Config) ApplyDefaults() {
defaults := DefaultConfig()
if c.Host == "" && c.URL == "" {
c.Host = defaults.Host
}
if c.Port == 0 {
c.Port = defaults.Port
}
if c.Username == "" {
c.Username = defaults.Username
}
if c.Password == "" {
c.Password = defaults.Password
}
if c.VHost == "" {
c.VHost = defaults.VHost
}
if c.MaxConnections == 0 {
c.MaxConnections = defaults.MaxConnections
}
if c.MaxChannels == 0 {
c.MaxChannels = defaults.MaxChannels
}
if c.ConnectionTimeout == 0 {
c.ConnectionTimeout = defaults.ConnectionTimeout
}
if c.HeartbeatInterval == 0 {
c.HeartbeatInterval = defaults.HeartbeatInterval
}
if c.ReconnectDelay == 0 {
c.ReconnectDelay = defaults.ReconnectDelay
}
if c.MaxReconnectDelay == 0 {
c.MaxReconnectDelay = defaults.MaxReconnectDelay
}
if c.ReconnectAttempts == 0 {
c.ReconnectAttempts = defaults.ReconnectAttempts
}
if c.HealthCheckInterval == 0 {
c.HealthCheckInterval = defaults.HealthCheckInterval
}
// Apply publisher defaults
if c.PublisherConfig.RetryAttempts == 0 {
c.PublisherConfig.RetryAttempts = defaults.PublisherConfig.RetryAttempts
}
if c.PublisherConfig.RetryDelay == 0 {
c.PublisherConfig.RetryDelay = defaults.PublisherConfig.RetryDelay
}
if c.PublisherConfig.ConfirmTimeout == 0 {
c.PublisherConfig.ConfirmTimeout = defaults.PublisherConfig.ConfirmTimeout
}
}
func (c *Config) Clone() *Config {
clone := *c
// Deep copy publisher config
clone.PublisherConfig = c.PublisherConfig
if c.PublisherConfig.Args != nil {
clone.PublisherConfig.Args = make(map[string]interface{})
for k, v := range c.PublisherConfig.Args {
clone.PublisherConfig.Args[k] = v
}
}
return &clone
}