MM-40818: Refactor product initialization to happen late (#19658)
This is more of a general refactor of the initialization process which should allow us to pass services more easily. The changes are minimal to keep the scope limited. For now, the objective is to pass the file service to the Channels product. For that, it was required to move some of the enterprise interfaces under Channels from Server. We also create a filestore field in the server to avoid creating filestore reference every time we make a filestore operation. This will be later passed on to the Channels product. Also removed an unnecessary test. The test was working so far because we were creating the filebackend every time for every request. But we should go via UpdateConfig call which would fail, were we to assign an invalid filestore name. So we were actually testing for a different thing. Therefore, removed the test. ```release-note NONE ```
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
768fe43d3a
Коммит
ab8de49f0a
123
app/server.go
123
app/server.go
@@ -159,6 +159,7 @@ type Server struct {
|
||||
searchLicenseListenerId string
|
||||
loggerLicenseListenerId string
|
||||
configStore *configWrapper
|
||||
filestore filestore.FileBackend
|
||||
|
||||
telemetryService *telemetry.TelemetryService
|
||||
userService *users.UserService
|
||||
@@ -184,10 +185,7 @@ type Server struct {
|
||||
Cluster einterfaces.ClusterInterface
|
||||
Cloud einterfaces.CloudInterface
|
||||
Metrics einterfaces.MetricsInterface
|
||||
Notification einterfaces.NotificationInterface
|
||||
LicenseManager einterfaces.LicenseInterface
|
||||
Saml einterfaces.SamlInterface
|
||||
Ldap einterfaces.LdapInterface
|
||||
|
||||
CacheProvider cache.Provider
|
||||
|
||||
@@ -257,27 +255,8 @@ func NewServer(options ...Option) (*Server, error) {
|
||||
mlog.Info("Server is initializing...", mlog.String("go_version", runtime.Version()))
|
||||
|
||||
s.httpService = httpservice.MakeHTTPService(s)
|
||||
s.licenseWrapper = &licenseWrapper{
|
||||
srv: s,
|
||||
}
|
||||
|
||||
serviceMap := map[ServiceKey]interface{}{
|
||||
ConfigKey: s.configStore,
|
||||
LicenseKey: s.licenseWrapper,
|
||||
}
|
||||
|
||||
// Step 3: Initialize products.
|
||||
// Depends on s.httpService.
|
||||
for name, initializer := range products {
|
||||
prod, err2 := initializer(s, serviceMap)
|
||||
if err2 != nil {
|
||||
return nil, errors.Wrapf(err2, "error initializing product: %s", name)
|
||||
}
|
||||
|
||||
s.products[name] = prod
|
||||
}
|
||||
|
||||
// Step 4: Search Engine
|
||||
// Step 3: Search Engine
|
||||
// Depends on Step 1 (config).
|
||||
searchEngine := searchengine.NewBroker(s.Config())
|
||||
bleveEngine := bleveengine.NewBleveEngine(s.Config())
|
||||
@@ -287,12 +266,11 @@ func NewServer(options ...Option) (*Server, error) {
|
||||
searchEngine.RegisterBleveEngine(bleveEngine)
|
||||
s.SearchEngine = searchEngine
|
||||
|
||||
// Step 5: Init Enterprise
|
||||
// Depends on step 3 (s.Channels() must be non-nil)
|
||||
// and step 4 (s.SearchEngine must be non-nil)
|
||||
// Step 4: Init Enterprise
|
||||
// Depends on step 3 (s.SearchEngine must be non-nil)
|
||||
s.initEnterprise()
|
||||
|
||||
// Step 6: Cache provider.
|
||||
// Step 5: Cache provider.
|
||||
// At the moment we only have this implementation
|
||||
// in the future the cache provider will be built based on the loaded config
|
||||
s.CacheProvider = cache.NewProvider()
|
||||
@@ -300,12 +278,8 @@ func NewServer(options ...Option) (*Server, error) {
|
||||
return nil, errors.Wrapf(err2, "Unable to connect to cache provider")
|
||||
}
|
||||
|
||||
// It is important to initialize the hub only after the global logger is set
|
||||
// to avoid race conditions while logging from inside the hub.
|
||||
s.HubStart()
|
||||
|
||||
// Step 7: Store.
|
||||
// Depends on Step 1 (config), 5 (metrics, cluster) and 6 (cacheProvider).
|
||||
// Step 6: Store.
|
||||
// Depends on Step 1 (config), 4 (metrics, cluster) and 5 (cacheProvider).
|
||||
if s.newStore == nil {
|
||||
s.newStore = func() (store.Store, error) {
|
||||
s.sqlStore = sqlstore.New(s.Config().SqlSettings, s.Metrics)
|
||||
@@ -347,6 +321,42 @@ func NewServer(options ...Option) (*Server, error) {
|
||||
return nil, errors.Wrap(err, "cannot create store")
|
||||
}
|
||||
|
||||
if model.BuildEnterpriseReady == "true" {
|
||||
s.LoadLicense()
|
||||
}
|
||||
|
||||
license := s.License()
|
||||
// Step 7: Initialize filestore
|
||||
backend, err := filestore.NewFileBackend(s.Config().FileSettings.ToFileBackendSettings(license != nil && *license.Features.Compliance))
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to initialize filebackend")
|
||||
}
|
||||
s.filestore = backend
|
||||
|
||||
s.licenseWrapper = &licenseWrapper{
|
||||
srv: s,
|
||||
}
|
||||
|
||||
serviceMap := map[ServiceKey]interface{}{
|
||||
ConfigKey: s.configStore,
|
||||
LicenseKey: s.licenseWrapper,
|
||||
}
|
||||
// Step 8: Initialize products.
|
||||
// Depends on s.httpService.
|
||||
for name, initializer := range products {
|
||||
prod, err2 := initializer(s, serviceMap)
|
||||
if err2 != nil {
|
||||
return nil, errors.Wrapf(err2, "error initializing product: %s", name)
|
||||
}
|
||||
|
||||
s.products[name] = prod
|
||||
}
|
||||
|
||||
// It is important to initialize the hub only after the global logger is set
|
||||
// to avoid race conditions while logging from inside the hub.
|
||||
// Step 9: Hub depends on s.Channels() (step 8)
|
||||
s.HubStart()
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Everything below this is not order sensitive and safe to be moved around.
|
||||
// If you are adding a new field that is non-channels specific, please add
|
||||
@@ -503,10 +513,6 @@ func NewServer(options ...Option) (*Server, error) {
|
||||
}
|
||||
s.EmailService = emailService
|
||||
|
||||
if model.BuildEnterpriseReady == "true" {
|
||||
s.LoadLicense()
|
||||
}
|
||||
|
||||
s.setupFeatureFlags()
|
||||
|
||||
s.initJobs()
|
||||
@@ -560,7 +566,6 @@ func NewServer(options ...Option) (*Server, error) {
|
||||
mlog.Info("Printing current working", mlog.String("directory", pwd))
|
||||
mlog.Info("Loaded config", mlog.String("source", s.configStore.String()))
|
||||
|
||||
license := s.License()
|
||||
allowAdvancedLogging := license != nil && *license.Features.AdvancedLogging
|
||||
|
||||
if s.Audit == nil {
|
||||
@@ -1172,18 +1177,13 @@ func (s *Server) Start() error {
|
||||
mlog.Error("Mail server connection test is failed", mlog.Err(err))
|
||||
}
|
||||
|
||||
backend, appErr := s.FileBackend()
|
||||
if appErr != nil {
|
||||
mlog.Error("Problem with file storage settings", mlog.Err(appErr))
|
||||
} else {
|
||||
err := backend.TestConnection()
|
||||
err := s.FileBackend().TestConnection()
|
||||
if err != nil {
|
||||
if _, ok := err.(*filestore.S3FileBackendNoBucketError); ok {
|
||||
err = s.FileBackend().(*filestore.S3FileBackend).MakeBucket()
|
||||
}
|
||||
if err != nil {
|
||||
if _, ok := err.(*filestore.S3FileBackendNoBucketError); ok {
|
||||
err = backend.(*filestore.S3FileBackend).MakeBucket()
|
||||
}
|
||||
if err != nil {
|
||||
mlog.Error("Problem with file storage settings", mlog.Err(err))
|
||||
}
|
||||
mlog.Error("Problem with file storage settings", mlog.Err(err))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1227,9 +1227,9 @@ func (s *Server) Start() error {
|
||||
if *s.Config().RateLimitSettings.Enable {
|
||||
mlog.Info("RateLimiter is enabled")
|
||||
|
||||
rateLimiter, err := NewRateLimiter(&s.Config().RateLimitSettings, s.Config().ServiceSettings.TrustedProxyIPHeader)
|
||||
if err != nil {
|
||||
return err
|
||||
rateLimiter, err2 := NewRateLimiter(&s.Config().RateLimitSettings, s.Config().ServiceSettings.TrustedProxyIPHeader)
|
||||
if err2 != nil {
|
||||
return err2
|
||||
}
|
||||
|
||||
s.RateLimiter = rateLimiter
|
||||
@@ -1850,13 +1850,8 @@ func (s *Server) stopSearchEngine() {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) FileBackend() (filestore.FileBackend, *model.AppError) {
|
||||
license := s.License()
|
||||
backend, err := filestore.NewFileBackend(s.Config().FileSettings.ToFileBackendSettings(license != nil && *license.Features.Compliance))
|
||||
if err != nil {
|
||||
return nil, model.NewAppError("FileBackend", "api.file.no_driver.app_error", nil, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
return backend, nil
|
||||
func (s *Server) FileBackend() filestore.FileBackend {
|
||||
return s.filestore
|
||||
}
|
||||
|
||||
func (s *Server) TotalWebsocketConnections() int {
|
||||
@@ -1904,7 +1899,7 @@ func (s *Server) initJobs() {
|
||||
}
|
||||
|
||||
if jobsLdapSyncInterface != nil {
|
||||
builder := jobsLdapSyncInterface(s)
|
||||
builder := jobsLdapSyncInterface(New(ServerConnector(s.Channels())))
|
||||
s.Jobs.RegisterJobType(model.JobTypeLdapSync, builder.MakeWorker(), builder.MakeScheduler())
|
||||
}
|
||||
|
||||
@@ -2189,7 +2184,7 @@ func (a *App) generateSupportPacketYaml() (*model.FileData, string) {
|
||||
}
|
||||
|
||||
// Here we are getting information regarding LDAP
|
||||
ldapInterface := a.ch.srv.Ldap
|
||||
ldapInterface := a.ch.Ldap
|
||||
var vendorName, vendorVersion string
|
||||
if ldapInterface != nil {
|
||||
vendorName, vendorVersion = ldapInterface.GetVendorNameAndVendorVersion()
|
||||
@@ -2270,11 +2265,7 @@ func (s *Server) GetDefaultProfileImage(user *model.User) ([]byte, *model.AppErr
|
||||
}
|
||||
|
||||
func (s *Server) ReadFile(path string) ([]byte, *model.AppError) {
|
||||
backend, err := s.FileBackend()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result, nErr := backend.ReadFile(path)
|
||||
result, nErr := s.FileBackend().ReadFile(path)
|
||||
if nErr != nil {
|
||||
return nil, model.NewAppError("ReadFile", "api.file.read_file.app_error", nil, nErr.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
Ссылка в новой задаче
Block a user