Migrate to stateless app.App (#17542)
* add request context * move initialialization to server * use app interface instead of global app functions * remove app context from webconn * cleanup * remove duplicated services * move context to separate package * remove finalize init method and move content to NewServer function * restart workers and schedulers after adding license for tests * reflect review comments Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
c09369f14a
Коммит
5ea06e51d0
160
app/server.go
160
app/server.go
@@ -11,7 +11,6 @@ import (
|
||||
"fmt"
|
||||
"hash/maphash"
|
||||
"html/template"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
@@ -39,6 +38,7 @@ import (
|
||||
"github.com/rs/cors"
|
||||
"golang.org/x/crypto/acme/autocert"
|
||||
|
||||
"github.com/mattermost/mattermost-server/v5/app/request"
|
||||
"github.com/mattermost/mattermost-server/v5/audit"
|
||||
"github.com/mattermost/mattermost-server/v5/config"
|
||||
"github.com/mattermost/mattermost-server/v5/einterfaces"
|
||||
@@ -77,10 +77,9 @@ var MaxNotificationsPerChannelDefault int64 = 1000000
|
||||
var SentryDSN = "placeholder_sentry_dsn"
|
||||
|
||||
type Server struct {
|
||||
sqlStore *sqlstore.SqlStore
|
||||
Store store.Store
|
||||
WebSocketRouter *WebSocketRouter
|
||||
AppInitializedOnce sync.Once
|
||||
sqlStore *sqlstore.SqlStore
|
||||
Store store.Store
|
||||
WebSocketRouter *WebSocketRouter
|
||||
|
||||
// RootRouter is the starting point for all HTTP requests to the server.
|
||||
RootRouter *mux.Router
|
||||
@@ -176,6 +175,7 @@ type Server struct {
|
||||
joinCluster bool
|
||||
startMetrics bool
|
||||
startSearchEngine bool
|
||||
skipPostInit bool
|
||||
|
||||
SearchEngine *searchengine.Broker
|
||||
|
||||
@@ -642,6 +642,48 @@ func NewServer(options ...Option) (*Server, error) {
|
||||
}()
|
||||
}
|
||||
|
||||
if s.skipPostInit {
|
||||
return s, nil
|
||||
}
|
||||
|
||||
c := request.EmptyContext()
|
||||
s.AddConfigListener(func(oldConfig *model.Config, newConfig *model.Config) {
|
||||
if *oldConfig.GuestAccountsSettings.Enable && !*newConfig.GuestAccountsSettings.Enable {
|
||||
if appErr := fakeApp.DeactivateGuests(c); appErr != nil {
|
||||
mlog.Error("Unable to deactivate guest accounts", mlog.Err(appErr))
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// Disable active guest accounts on first run if guest accounts are disabled
|
||||
if !*s.Config().GuestAccountsSettings.Enable {
|
||||
if appErr := fakeApp.DeactivateGuests(c); appErr != nil {
|
||||
mlog.Error("Unable to deactivate guest accounts", mlog.Err(appErr))
|
||||
}
|
||||
}
|
||||
|
||||
s.doAppMigrations()
|
||||
|
||||
s.initPostMetadata()
|
||||
|
||||
s.initPlugins(c, *s.Config().PluginSettings.Directory, *s.Config().PluginSettings.ClientDirectory)
|
||||
s.AddConfigListener(func(prevCfg, cfg *model.Config) {
|
||||
if *cfg.PluginSettings.Enable {
|
||||
s.initPlugins(c, *cfg.PluginSettings.Directory, *s.Config().PluginSettings.ClientDirectory)
|
||||
} else {
|
||||
s.ShutDownPlugins()
|
||||
}
|
||||
})
|
||||
if s.runEssentialJobs {
|
||||
s.Go(func() {
|
||||
s.runLicenseExpirationCheckJob()
|
||||
runCheckAdminSupportStatusJob(fakeApp, c)
|
||||
runCheckWarnMetricStatusJob(fakeApp, c)
|
||||
runDNDStatusExpireJob(fakeApp)
|
||||
})
|
||||
s.runJobs()
|
||||
}
|
||||
|
||||
return s, nil
|
||||
}
|
||||
|
||||
@@ -1400,10 +1442,10 @@ func runSessionCleanupJob(s *Server) {
|
||||
}, time.Hour*24)
|
||||
}
|
||||
|
||||
func runLicenseExpirationCheckJob(a *App) {
|
||||
doLicenseExpirationCheck(a)
|
||||
func (s *Server) runLicenseExpirationCheckJob() {
|
||||
s.doLicenseExpirationCheck()
|
||||
model.CreateRecurringTask("License Expiration Check", func() {
|
||||
doLicenseExpirationCheck(a)
|
||||
s.doLicenseExpirationCheck()
|
||||
}, time.Hour*24)
|
||||
}
|
||||
|
||||
@@ -1426,17 +1468,17 @@ func doReportUsageToAWSMeteringService(s *Server) {
|
||||
}
|
||||
|
||||
//nolint:golint,unused,deadcode
|
||||
func runCheckWarnMetricStatusJob(a *App) {
|
||||
doCheckWarnMetricStatus(a)
|
||||
func runCheckWarnMetricStatusJob(a *App, c *request.Context) {
|
||||
doCheckWarnMetricStatus(a, c)
|
||||
model.CreateRecurringTask("Check Warn Metric Status Job", func() {
|
||||
doCheckWarnMetricStatus(a)
|
||||
doCheckWarnMetricStatus(a, c)
|
||||
}, time.Hour*model.WARN_METRIC_JOB_INTERVAL)
|
||||
}
|
||||
|
||||
func runCheckAdminSupportStatusJob(a *App) {
|
||||
doCheckAdminSupportStatus(a)
|
||||
func runCheckAdminSupportStatusJob(a *App, c *request.Context) {
|
||||
doCheckAdminSupportStatus(a, c)
|
||||
model.CreateRecurringTask("Check Admin Support Status Job", func() {
|
||||
doCheckAdminSupportStatus(a)
|
||||
doCheckAdminSupportStatus(a, c)
|
||||
}, time.Hour*model.WARN_METRIC_JOB_INTERVAL)
|
||||
}
|
||||
|
||||
@@ -1461,7 +1503,7 @@ func doSessionCleanup(s *Server) {
|
||||
}
|
||||
|
||||
//nolint:golint,unused,deadcode
|
||||
func doCheckWarnMetricStatus(a *App) {
|
||||
func doCheckWarnMetricStatus(a *App, c *request.Context) {
|
||||
license := a.Srv().License()
|
||||
if license != nil {
|
||||
mlog.Debug("License is present, skip")
|
||||
@@ -1592,7 +1634,7 @@ func doCheckWarnMetricStatus(a *App) {
|
||||
}
|
||||
}
|
||||
|
||||
if nerr := a.notifyAdminsOfWarnMetricStatus(warnMetric.Id, isE0Edition); nerr != nil {
|
||||
if nerr := a.notifyAdminsOfWarnMetricStatus(c, warnMetric.Id, isE0Edition); nerr != nil {
|
||||
mlog.Error("Failed to send notifications to admin users.", mlog.Err(nerr))
|
||||
}
|
||||
|
||||
@@ -1604,11 +1646,11 @@ func doCheckWarnMetricStatus(a *App) {
|
||||
}
|
||||
}
|
||||
|
||||
func doCheckAdminSupportStatus(a *App) {
|
||||
func doCheckAdminSupportStatus(a *App, c *request.Context) {
|
||||
isE0Edition := model.BuildEnterpriseReady == "true"
|
||||
|
||||
if strings.TrimSpace(*a.Config().SupportSettings.SupportEmail) == model.SUPPORT_SETTINGS_DEFAULT_SUPPORT_EMAIL {
|
||||
if err := a.notifyAdminsOfWarnMetricStatus(model.SYSTEM_METRIC_SUPPORT_EMAIL_NOT_CONFIGURED, isE0Edition); err != nil {
|
||||
if err := a.notifyAdminsOfWarnMetricStatus(c, model.SYSTEM_METRIC_SUPPORT_EMAIL_NOT_CONFIGURED, isE0Edition); err != nil {
|
||||
mlog.Error("Failed to send notifications to admin users.", mlog.Err(err))
|
||||
}
|
||||
}
|
||||
@@ -1714,9 +1756,9 @@ func (s *Server) startMetricsServer() {
|
||||
s.Log.Info("Metrics and profiling server is started", mlog.String("address", l.Addr().String()))
|
||||
}
|
||||
|
||||
func doLicenseExpirationCheck(a *App) {
|
||||
a.Srv().LoadLicense()
|
||||
license := a.Srv().License()
|
||||
func (s *Server) doLicenseExpirationCheck() {
|
||||
s.LoadLicense()
|
||||
license := s.License()
|
||||
|
||||
if license == nil {
|
||||
mlog.Debug("License cannot be found.")
|
||||
@@ -1728,7 +1770,7 @@ func doLicenseExpirationCheck(a *App) {
|
||||
return
|
||||
}
|
||||
|
||||
users, err := a.Srv().Store.User().GetSystemAdminProfiles()
|
||||
users, err := s.Store.User().GetSystemAdminProfiles()
|
||||
if err != nil {
|
||||
mlog.Error("Failed to get system admins for license expired message from Mattermost.")
|
||||
return
|
||||
@@ -1743,15 +1785,15 @@ func doLicenseExpirationCheck(a *App) {
|
||||
}
|
||||
|
||||
mlog.Debug("Sending license expired email.", mlog.String("user_email", user.Email))
|
||||
a.Srv().Go(func() {
|
||||
if err := a.Srv().EmailService.SendRemoveExpiredLicenseEmail(user.Email, user.Locale, *a.Config().ServiceSettings.SiteURL); err != nil {
|
||||
s.Go(func() {
|
||||
if err := s.EmailService.SendRemoveExpiredLicenseEmail(user.Email, user.Locale, *s.Config().ServiceSettings.SiteURL); err != nil {
|
||||
mlog.Error("Error while sending the license expired email.", mlog.String("user_email", user.Email), mlog.Err(err))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
//remove the license
|
||||
a.Srv().RemoveLicense()
|
||||
s.RemoveLicense()
|
||||
}
|
||||
|
||||
func (s *Server) StartSearchEngine() (string, string) {
|
||||
@@ -1884,6 +1926,50 @@ func (s *Server) initJobs() {
|
||||
if jobsMigrationsInterface != nil {
|
||||
s.Jobs.Migrations = jobsMigrationsInterface(s)
|
||||
}
|
||||
if jobsLdapSyncInterface != nil {
|
||||
s.Jobs.LdapSync = jobsLdapSyncInterface(s)
|
||||
}
|
||||
if jobsPluginsInterface != nil {
|
||||
s.Jobs.Plugins = jobsPluginsInterface(s)
|
||||
}
|
||||
if jobsExpiryNotifyInterface != nil {
|
||||
s.Jobs.ExpiryNotify = jobsExpiryNotifyInterface(s)
|
||||
}
|
||||
if productNoticesJobInterface != nil {
|
||||
s.Jobs.ProductNotices = productNoticesJobInterface(s)
|
||||
}
|
||||
if jobsImportProcessInterface != nil {
|
||||
s.Jobs.ImportProcess = jobsImportProcessInterface(s)
|
||||
}
|
||||
if jobsImportDeleteInterface != nil {
|
||||
s.Jobs.ImportDelete = jobsImportDeleteInterface(s)
|
||||
}
|
||||
if jobsExportDeleteInterface != nil {
|
||||
s.Jobs.ExportDelete = jobsExportDeleteInterface(s)
|
||||
}
|
||||
|
||||
if jobsExportProcessInterface != nil {
|
||||
s.Jobs.ExportProcess = jobsExportProcessInterface(s)
|
||||
}
|
||||
|
||||
if jobsExportProcessInterface != nil {
|
||||
s.Jobs.ExportProcess = jobsExportProcessInterface(s)
|
||||
}
|
||||
|
||||
if jobsActiveUsersInterface != nil {
|
||||
s.Jobs.ActiveUsers = jobsActiveUsersInterface(s)
|
||||
}
|
||||
|
||||
if jobsCloudInterface != nil {
|
||||
s.Jobs.Cloud = jobsCloudInterface(s)
|
||||
}
|
||||
|
||||
if jobsResendInvitationEmailInterface != nil {
|
||||
s.Jobs.ResendInvitationEmails = jobsResendInvitationEmailInterface(s)
|
||||
}
|
||||
|
||||
s.Jobs.InitWorkers()
|
||||
s.Jobs.InitSchedulers()
|
||||
}
|
||||
|
||||
func (s *Server) TelemetryId() string {
|
||||
@@ -2135,7 +2221,7 @@ func (s *Server) GetProfileImage(user *model.User) ([]byte, bool, *model.AppErro
|
||||
}
|
||||
|
||||
if user.LastPictureUpdate == 0 {
|
||||
if _, err := s.WriteFile(bytes.NewReader(img), path); err != nil {
|
||||
if _, err := s.writeFile(bytes.NewReader(img), path); err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
}
|
||||
@@ -2173,18 +2259,18 @@ func (s *Server) ReadFile(path string) ([]byte, *model.AppError) {
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (s *Server) WriteFile(fr io.Reader, path string) (int64, *model.AppError) {
|
||||
backend, err := s.FileBackend()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
// func (s *Server) WriteFile(fr io.Reader, path string) (int64, *model.AppError) {
|
||||
// backend, err := s.FileBackend()
|
||||
// if err != nil {
|
||||
// return 0, err
|
||||
// }
|
||||
|
||||
result, nErr := backend.WriteFile(fr, path)
|
||||
if nErr != nil {
|
||||
return result, model.NewAppError("WriteFile", "api.file.write_file.app_error", nil, nErr.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
// result, nErr := backend.WriteFile(fr, path)
|
||||
// if nErr != nil {
|
||||
// return result, model.NewAppError("WriteFile", "api.file.write_file.app_error", nil, nErr.Error(), http.StatusInternalServerError)
|
||||
// }
|
||||
// return result, nil
|
||||
// }
|
||||
|
||||
func runDNDStatusExpireJob(a *App) {
|
||||
if a.IsLeader() {
|
||||
|
||||
Ссылка в новой задаче
Block a user