diff options
-rw-r--r-- | app/diagnostics.go | 15 | ||||
-rw-r--r-- | config/default.json | 1 | ||||
-rw-r--r-- | i18n/en.json | 58 | ||||
-rw-r--r-- | model/config.go | 27 | ||||
-rw-r--r-- | store/sqlstore/supplier.go | 3 | ||||
-rw-r--r-- | store/sqlstore/supplier_test.go | 32 | ||||
-rw-r--r-- | store/storetest/docker.go | 20 |
7 files changed, 88 insertions, 68 deletions
diff --git a/app/diagnostics.go b/app/diagnostics.go index 3df62c41d..e9b3405be 100644 --- a/app/diagnostics.go +++ b/app/diagnostics.go @@ -297,13 +297,14 @@ func (a *App) trackConfig() { }) a.SendDiagnostic(TRACK_CONFIG_SQL, map[string]interface{}{ - "driver_name": *cfg.SqlSettings.DriverName, - "trace": cfg.SqlSettings.Trace, - "max_idle_conns": *cfg.SqlSettings.MaxIdleConns, - "max_open_conns": *cfg.SqlSettings.MaxOpenConns, - "data_source_replicas": len(cfg.SqlSettings.DataSourceReplicas), - "data_source_search_replicas": len(cfg.SqlSettings.DataSourceSearchReplicas), - "query_timeout": *cfg.SqlSettings.QueryTimeout, + "driver_name": *cfg.SqlSettings.DriverName, + "trace": cfg.SqlSettings.Trace, + "max_idle_conns": *cfg.SqlSettings.MaxIdleConns, + "conn_max_lifetime_milliseconds": *cfg.SqlSettings.ConnMaxLifetimeMilliseconds, + "max_open_conns": *cfg.SqlSettings.MaxOpenConns, + "data_source_replicas": len(cfg.SqlSettings.DataSourceReplicas), + "data_source_search_replicas": len(cfg.SqlSettings.DataSourceSearchReplicas), + "query_timeout": *cfg.SqlSettings.QueryTimeout, }) a.SendDiagnostic(TRACK_CONFIG_LOG, map[string]interface{}{ diff --git a/config/default.json b/config/default.json index 2d1e6ceec..6e4f6d1eb 100644 --- a/config/default.json +++ b/config/default.json @@ -119,6 +119,7 @@ "DataSourceReplicas": [], "DataSourceSearchReplicas": [], "MaxIdleConns": 20, + "ConnMaxLifetimeMilliseconds": 3600000, "MaxOpenConns": 300, "Trace": false, "AtRestEncryptKey": "", diff --git a/i18n/en.json b/i18n/en.json index 6c7b44443..fd9888e39 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -3064,11 +3064,11 @@ }, { "id": "ent.cluster.config_changed.info", - "translation": "Cluster configuration has changed for id={{ .id }}. The cluster may become unstable and a restart is required. To ensure the cluster is configured correctly you should perform a rolling restart immediately." + "translation": "Cluster configuration has changed for id={{ .id }}. The cluster may become unstable and a restart is required. To ensure the cluster is configured correctly you should perform a rolling restart immediately." }, { "id": "ent.cluster.save_config.error", - "translation": "System Console is set to read-only when High Availability is enabled unless ReadOnlyConfig is disabled in the configuration file." + "translation": "System Console is set to read-only when High Availability is enabled unless ReadOnlyConfig is disabled in the configuration file." }, { "id": "ent.compliance.bad_export_type.appError", @@ -3812,11 +3812,11 @@ }, { "id": "model.config.is_valid.email_batching_buffer_size.app_error", - "translation": "Invalid email batching buffer size for email settings. Must be zero or a positive number." + "translation": "Invalid email batching buffer size for email settings. Must be zero or a positive number." }, { "id": "model.config.is_valid.email_batching_interval.app_error", - "translation": "Invalid email batching interval for email settings. Must be 30 seconds or more." + "translation": "Invalid email batching interval for email settings. Must be 30 seconds or more." }, { "id": "model.config.is_valid.email_notification_contents_type.app_error", @@ -3824,23 +3824,23 @@ }, { "id": "model.config.is_valid.email_salt.app_error", - "translation": "Invalid invite salt for email settings. Must be 32 chars or more." + "translation": "Invalid invite salt for email settings. Must be 32 chars or more." }, { "id": "model.config.is_valid.email_security.app_error", - "translation": "Invalid connection security for email settings. Must be '', 'TLS', or 'STARTTLS'" + "translation": "Invalid connection security for email settings. Must be '', 'TLS', or 'STARTTLS'" }, { "id": "model.config.is_valid.encrypt_sql.app_error", - "translation": "Invalid at rest encrypt key for SQL settings. Must be 32 chars or more." + "translation": "Invalid at rest encrypt key for SQL settings. Must be 32 chars or more." }, { "id": "model.config.is_valid.file_driver.app_error", - "translation": "Invalid driver name for file settings. Must be 'local' or 'amazons3'" + "translation": "Invalid driver name for file settings. Must be 'local' or 'amazons3'" }, { "id": "model.config.is_valid.file_salt.app_error", - "translation": "Invalid public link salt for file settings. Must be 32 chars or more." + "translation": "Invalid public link salt for file settings. Must be 32 chars or more." }, { "id": "model.config.is_valid.group_unread_channels.app_error", @@ -3872,7 +3872,7 @@ }, { "id": "model.config.is_valid.ldap_security.app_error", - "translation": "Invalid connection security for AD/LDAP settings. Must be '', 'TLS', or 'STARTTLS'" + "translation": "Invalid connection security for AD/LDAP settings. Must be '', 'TLS', or 'STARTTLS'" }, { "id": "model.config.is_valid.ldap_server", @@ -3896,7 +3896,7 @@ }, { "id": "model.config.is_valid.login_attempts.app_error", - "translation": "Invalid maximum login attempts for service settings. Must be a positive number." + "translation": "Invalid maximum login attempts for service settings. Must be a positive number." }, { "id": "model.config.is_valid.max_burst.app_error", @@ -3904,7 +3904,7 @@ }, { "id": "model.config.is_valid.max_channels.app_error", - "translation": "Invalid maximum channels per team for team settings. Must be a positive number." + "translation": "Invalid maximum channels per team for team settings. Must be a positive number." }, { "id": "model.config.is_valid.max_file_size.app_error", @@ -3912,11 +3912,11 @@ }, { "id": "model.config.is_valid.max_notify_per_channel.app_error", - "translation": "Invalid maximum notifications per channel for team settings. Must be a positive number." + "translation": "Invalid maximum notifications per channel for team settings. Must be a positive number." }, { "id": "model.config.is_valid.max_users.app_error", - "translation": "Invalid maximum users per team for team settings. Must be a positive number." + "translation": "Invalid maximum users per team for team settings. Must be a positive number." }, { "id": "model.config.is_valid.message_export.batch_size.app_error", @@ -3964,11 +3964,11 @@ }, { "id": "model.config.is_valid.rate_mem.app_error", - "translation": "Invalid memory store size for rate limit settings. Must be a positive number" + "translation": "Invalid memory store size for rate limit settings. Must be a positive number" }, { "id": "model.config.is_valid.rate_sec.app_error", - "translation": "Invalid per sec for rate limit settings. Must be a positive number" + "translation": "Invalid per sec for rate limit settings. Must be a positive number" }, { "id": "model.config.is_valid.read_timeout.app_error", @@ -3976,7 +3976,7 @@ }, { "id": "model.config.is_valid.restrict_direct_message.app_error", - "translation": "Invalid direct message restriction. Must be 'any', or 'team'" + "translation": "Invalid direct message restriction. Must be 'any', or 'team'" }, { "id": "model.config.is_valid.saml_assertion_consumer_service_url.app_error", @@ -4024,27 +4024,31 @@ }, { "id": "model.config.is_valid.sql_data_src.app_error", - "translation": "Invalid data source for SQL settings. Must be set." + "translation": "Invalid data source for SQL settings. Must be set." }, { "id": "model.config.is_valid.sql_driver.app_error", - "translation": "Invalid driver name for SQL settings. Must be 'mysql' or 'postgres'" + "translation": "Invalid driver name for SQL settings. Must be 'mysql' or 'postgres'" }, { "id": "model.config.is_valid.sql_idle.app_error", - "translation": "Invalid maximum idle connection for SQL settings. Must be a positive number." + "translation": "Invalid maximum idle connection for SQL settings. Must be a positive number." }, { "id": "model.config.is_valid.sql_max_conn.app_error", - "translation": "Invalid maximum open connection for SQL settings. Must be a positive number." + "translation": "Invalid maximum open connection for SQL settings. Must be a positive number." + }, + { + "id": "model.config.is_valid.sql_conn_max_lifetime_milliseconds.app_error", + "translation": "Invalid connection maximum lifetime for SQL settings. Must be a non-negative number." }, { "id": "model.config.is_valid.sql_query_timeout.app_error", - "translation": "Invalid query timeout for SQL settings. Must be a positive number." + "translation": "Invalid query timeout for SQL settings. Must be a positive number." }, { "id": "model.config.is_valid.teammate_name_display.app_error", - "translation": "Invalid teammate display. Must be 'full_name', 'nickname_full_name' or 'username'" + "translation": "Invalid teammate display. Must be 'full_name', 'nickname_full_name' or 'username'" }, { "id": "model.config.is_valid.time_between_user_typing.app_error", @@ -6040,7 +6044,7 @@ }, { "id": "utils.config.add_client_locale.app_error", - "translation": "Unable to load mattermost configuration file: Adding DefaultClientLocale to AvailableLocales." + "translation": "Unable to load mattermost configuration file: Adding DefaultClientLocale to AvailableLocales." }, { "id": "utils.config.load_config.decoding.panic", @@ -6056,15 +6060,15 @@ }, { "id": "utils.config.supported_available_locales.app_error", - "translation": "Unable to load mattermost configuration file: AvailableLocales must include DefaultClientLocale. Setting AvailableLocales to all locales as default value." + "translation": "Unable to load mattermost configuration file: AvailableLocales must include DefaultClientLocale. Setting AvailableLocales to all locales as default value." }, { "id": "utils.config.supported_client_locale.app_error", - "translation": "Unable to load mattermost configuration file: DefaultClientLocale must be one of the supported locales. Setting DefaultClientLocale to en as default value." + "translation": "Unable to load mattermost configuration file: DefaultClientLocale must be one of the supported locales. Setting DefaultClientLocale to en as default value." }, { "id": "utils.config.supported_server_locale.app_error", - "translation": "Unable to load mattermost configuration file: DefaultServerLocale must be one of the supported locales. Setting DefaultServerLocale to en as default value." + "translation": "Unable to load mattermost configuration file: DefaultServerLocale must be one of the supported locales. Setting DefaultServerLocale to en as default value." }, { "id": "utils.file.list_directory.local.app_error", diff --git a/model/config.go b/model/config.go index ce66f2f05..e6bd04dfc 100644 --- a/model/config.go +++ b/model/config.go @@ -605,15 +605,16 @@ type SSOSettings struct { } type SqlSettings struct { - DriverName *string - DataSource *string - DataSourceReplicas []string - DataSourceSearchReplicas []string - MaxIdleConns *int - MaxOpenConns *int - Trace bool - AtRestEncryptKey string - QueryTimeout *int + DriverName *string + DataSource *string + DataSourceReplicas []string + DataSourceSearchReplicas []string + MaxIdleConns *int + ConnMaxLifetimeMilliseconds *int + MaxOpenConns *int + Trace bool + AtRestEncryptKey string + QueryTimeout *int } func (s *SqlSettings) SetDefaults() { @@ -637,6 +638,10 @@ func (s *SqlSettings) SetDefaults() { s.MaxOpenConns = NewInt(300) } + if s.ConnMaxLifetimeMilliseconds == nil { + s.ConnMaxLifetimeMilliseconds = NewInt(3600000) + } + if s.QueryTimeout == nil { s.QueryTimeout = NewInt(30) } @@ -2069,6 +2074,10 @@ func (ss *SqlSettings) isValid() *AppError { return NewAppError("Config.IsValid", "model.config.is_valid.sql_idle.app_error", nil, "", http.StatusBadRequest) } + if *ss.ConnMaxLifetimeMilliseconds < 0 { + return NewAppError("Config.IsValid", "model.config.is_valid.sql_conn_max_lifetime_milliseconds.app_error", nil, "", http.StatusBadRequest) + } + if *ss.QueryTimeout <= 0 { return NewAppError("Config.IsValid", "model.config.is_valid.sql_query_timeout.app_error", nil, "", http.StatusBadRequest) } diff --git a/store/sqlstore/supplier.go b/store/sqlstore/supplier.go index 1e6bdcba1..6c49d91fb 100644 --- a/store/sqlstore/supplier.go +++ b/store/sqlstore/supplier.go @@ -28,7 +28,6 @@ import ( const ( INDEX_TYPE_FULL_TEXT = "full_text" INDEX_TYPE_DEFAULT = "default" - MAX_DB_CONN_LIFETIME = 60 DB_PING_ATTEMPTS = 18 DB_PING_TIMEOUT_SECS = 10 ) @@ -218,7 +217,7 @@ func setupConnection(con_type string, dataSource string, settings *model.SqlSett db.SetMaxIdleConns(*settings.MaxIdleConns) db.SetMaxOpenConns(*settings.MaxOpenConns) - db.SetConnMaxLifetime(time.Duration(MAX_DB_CONN_LIFETIME) * time.Minute) + db.SetConnMaxLifetime(time.Duration(*settings.ConnMaxLifetimeMilliseconds) * time.Millisecond) var dbmap *gorp.DbMap diff --git a/store/sqlstore/supplier_test.go b/store/sqlstore/supplier_test.go index 5aacfbe6a..3835bd01f 100644 --- a/store/sqlstore/supplier_test.go +++ b/store/sqlstore/supplier_test.go @@ -73,17 +73,19 @@ func TestGetReplica(t *testing.T) { driverName := model.DATABASE_DRIVER_SQLITE dataSource := ":memory:" maxIdleConns := 1 + connMaxLifetimeMilliseconds := 3600000 maxOpenConns := 1 queryTimeout := 5 settings := model.SqlSettings{ - DriverName: &driverName, - DataSource: &dataSource, - MaxIdleConns: &maxIdleConns, - MaxOpenConns: &maxOpenConns, - QueryTimeout: &queryTimeout, - DataSourceReplicas: testCase.DataSourceReplicas, - DataSourceSearchReplicas: testCase.DataSourceSearchReplicas, + DriverName: &driverName, + DataSource: &dataSource, + MaxIdleConns: &maxIdleConns, + ConnMaxLifetimeMilliseconds: &connMaxLifetimeMilliseconds, + MaxOpenConns: &maxOpenConns, + QueryTimeout: &queryTimeout, + DataSourceReplicas: testCase.DataSourceReplicas, + DataSourceSearchReplicas: testCase.DataSourceSearchReplicas, } supplier := sqlstore.NewSqlSupplier(settings, nil) @@ -209,17 +211,19 @@ func TestGetAllConns(t *testing.T) { driverName := model.DATABASE_DRIVER_SQLITE dataSource := ":memory:" maxIdleConns := 1 + connMaxLifetimeMilliseconds := 3600000 maxOpenConns := 1 queryTimeout := 5 settings := model.SqlSettings{ - DriverName: &driverName, - DataSource: &dataSource, - MaxIdleConns: &maxIdleConns, - MaxOpenConns: &maxOpenConns, - QueryTimeout: &queryTimeout, - DataSourceReplicas: testCase.DataSourceReplicas, - DataSourceSearchReplicas: testCase.DataSourceSearchReplicas, + DriverName: &driverName, + DataSource: &dataSource, + MaxIdleConns: &maxIdleConns, + ConnMaxLifetimeMilliseconds: &connMaxLifetimeMilliseconds, + MaxOpenConns: &maxOpenConns, + QueryTimeout: &queryTimeout, + DataSourceReplicas: testCase.DataSourceReplicas, + DataSourceSearchReplicas: testCase.DataSourceSearchReplicas, } supplier := sqlstore.NewSqlSupplier(settings, nil) diff --git a/store/storetest/docker.go b/store/storetest/docker.go index f3830a6fe..f5b8807d0 100644 --- a/store/storetest/docker.go +++ b/store/storetest/docker.go @@ -76,17 +76,19 @@ func NewPostgreSQLContainer() (*RunningContainer, *model.SqlSettings, error) { func databaseSettings(driver, dataSource string) *model.SqlSettings { settings := &model.SqlSettings{ - DriverName: &driver, - DataSource: &dataSource, - DataSourceReplicas: []string{}, - DataSourceSearchReplicas: []string{}, - MaxIdleConns: new(int), - MaxOpenConns: new(int), - Trace: false, - AtRestEncryptKey: model.NewRandomString(32), - QueryTimeout: new(int), + DriverName: &driver, + DataSource: &dataSource, + DataSourceReplicas: []string{}, + DataSourceSearchReplicas: []string{}, + MaxIdleConns: new(int), + ConnMaxLifetimeMilliseconds: new(int), + MaxOpenConns: new(int), + Trace: false, + AtRestEncryptKey: model.NewRandomString(32), + QueryTimeout: new(int), } *settings.MaxIdleConns = 10 + *settings.ConnMaxLifetimeMilliseconds = 3600000 *settings.MaxOpenConns = 100 *settings.QueryTimeout = 10 return settings |