MM-61229: Place Redis behind enterprise (#28917)
And re-order the server initialization (AGAIN). For the nth time, we found several bugs in the initialization process. 1. filestore.NewExportFileBackend and filestore.NewFileBackend depended on license, but the license wasn't even loaded until later! 2. The `ps.sqlStore.UpdateLicense` call also didn't work because the license wouldn't get loaded. It only accidentally worked because of `ps.AddLicenseListener` which would update the license later on. We remove that. Ideally, we would have loaded the license first and then checked for redis client, but it's very difficult to do that. Reasons are explained in the code comment. So we just wait until the license is loaded, and simply throw an error later. https://mattermost.atlassian.net/browse/MM-61229 ```release-note NONE ``` --------- Co-authored-by: Mattermost Build <build@mattermost.com>
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
8933756aea
Коммит
8d1c42bc91
@@ -112,6 +112,7 @@ func setupTestHelper(dbStore store.Store, searchEngine *searchengine.Broker, ent
|
||||
*memoryConfig.CacheSettings.RedisAddress = redisHost + ":6379"
|
||||
*memoryConfig.CacheSettings.DisableClientCache = true
|
||||
*memoryConfig.CacheSettings.RedisDB = 0
|
||||
options = append(options, app.ForceEnableRedis())
|
||||
}
|
||||
if updateConfig != nil {
|
||||
updateConfig(memoryConfig)
|
||||
|
||||
@@ -59,6 +59,13 @@ func SetFileStore(filestore filestore.FileBackend) Option {
|
||||
}
|
||||
}
|
||||
|
||||
func ForceEnableRedis() Option {
|
||||
return func(s *Server) error {
|
||||
s.platformOptions = append(s.platformOptions, platform.ForceEnableRedis())
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func RunEssentialJobs(s *Server) error {
|
||||
s.runEssentialJobs = true
|
||||
|
||||
|
||||
@@ -119,3 +119,10 @@ func SetCluster(cluster einterfaces.ClusterInterface) Option {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func ForceEnableRedis() Option {
|
||||
return func(ps *PlatformService) error {
|
||||
ps.forceEnableRedis = true
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,6 +103,10 @@ type PlatformService struct {
|
||||
sharedChannelService SharedChannelServiceIFace
|
||||
|
||||
pluginEnv HookRunner
|
||||
|
||||
// This is a test mode setting used to enable Redis
|
||||
// without a license.
|
||||
forceEnableRedis bool
|
||||
}
|
||||
|
||||
type HookRunner interface {
|
||||
@@ -257,8 +261,26 @@ func New(sc ServiceConfig, options ...Option) (*PlatformService, error) {
|
||||
}
|
||||
}
|
||||
|
||||
ps.Store, err = ps.newStore()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot create store: %w", err)
|
||||
}
|
||||
|
||||
// Step 7: Init License
|
||||
if model.BuildEnterpriseReady == "true" {
|
||||
ps.LoadLicense()
|
||||
}
|
||||
license := ps.License()
|
||||
// Step 3: Initialize filestore
|
||||
|
||||
// This is a hack because ideally we wouldn't even have started the Redis client
|
||||
// if the license didn't have clustering. But there's an intricate deadlock
|
||||
// where license cannot be loaded before store, and store cannot be loaded before
|
||||
// cache. So loading license before loading cache is an uphill battle.
|
||||
if (license == nil || !*license.Features.Cluster) && *cacheConfig.CacheType == model.CacheTypeRedis && !ps.forceEnableRedis {
|
||||
return nil, fmt.Errorf("Redis cannot be used in an instance without a license or a license without clustering")
|
||||
}
|
||||
|
||||
// Step 8: Initialize filestore
|
||||
if ps.filestore == nil {
|
||||
insecure := ps.Config().ServiceSettings.EnableInsecureOutgoingConnections
|
||||
backend, err2 := filestore.NewFileBackend(filestore.NewFileBackendSettingsFromConfig(&ps.Config().FileSettings, license != nil && *license.Features.Compliance, insecure != nil && *insecure))
|
||||
@@ -282,17 +304,11 @@ func New(sc ServiceConfig, options ...Option) (*PlatformService, error) {
|
||||
}
|
||||
}
|
||||
|
||||
ps.Store, err = ps.newStore()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot create store: %w", err)
|
||||
}
|
||||
|
||||
// Note: we hardcode the session and status cache to LRU because they lead
|
||||
// to a lot of SCAN calls in case of Redis. We could potentially have a
|
||||
// reverse mapping to avoid the scan, but this needs more complicated code.
|
||||
// Leaving this for now.
|
||||
|
||||
// Needed before loading license
|
||||
ps.statusCache, err = cache.NewProvider().NewCache(&cache.CacheOptions{
|
||||
Name: "Status",
|
||||
Size: model.StatusCacheSize,
|
||||
@@ -314,12 +330,7 @@ func New(sc ServiceConfig, options ...Option) (*PlatformService, error) {
|
||||
return nil, fmt.Errorf("could not create session cache: %w", err)
|
||||
}
|
||||
|
||||
// Step 7: Init License
|
||||
if model.BuildEnterpriseReady == "true" {
|
||||
ps.LoadLicense()
|
||||
}
|
||||
|
||||
// Step 8: Init Metrics Server depends on step 6 (store) and 7 (license)
|
||||
// Step 9: Init Metrics Server depends on step 6 (store) and 7 (license)
|
||||
if ps.startMetrics {
|
||||
if mErr := ps.resetMetrics(); mErr != nil {
|
||||
return nil, mErr
|
||||
@@ -334,7 +345,7 @@ func New(sc ServiceConfig, options ...Option) (*PlatformService, error) {
|
||||
})
|
||||
}
|
||||
|
||||
// Step 9: Init AsymmetricSigningKey depends on step 6 (store)
|
||||
// Step 10: Init AsymmetricSigningKey depends on step 6 (store)
|
||||
if err = ps.EnsureAsymmetricSigningKey(); err != nil {
|
||||
return nil, fmt.Errorf("unable to ensure asymmetric signing key: %w", err)
|
||||
}
|
||||
|
||||
Ссылка в новой задаче
Block a user