From 5bfb32c504db299b6809b0f84213d27515b9380a Mon Sep 17 00:00:00 2001 From: Nick Misasi Date: Wed, 31 Jul 2024 08:31:55 -0400 Subject: [PATCH] [CLD-8131] Convert Subscription History Reporting to a Job (#27800) * Remove CloudFreeDeprecated feature flag * Fixes for CI pipelines * Remove CloudReverseTrial feature flag and accompanying code (#27676) Co-authored-by: Mattermost Build * Stashing * Convert subscription history reporting into a daily job * Update comments * Fix pipeline, redundant varaible declaration removed * Add debug logs for start/finish --------- Co-authored-by: Mattermost Build --- server/channels/app/app_iface.go | 1 + server/channels/app/cloud.go | 3 ++- server/channels/app/server.go | 31 +++++++++++++++++++++++++++++++ server/channels/app/user.go | 23 ----------------------- 4 files changed, 34 insertions(+), 24 deletions(-) diff --git a/server/channels/app/app_iface.go b/server/channels/app/app_iface.go index fa9d22cfb8..4646f10e1a 100644 --- a/server/channels/app/app_iface.go +++ b/server/channels/app/app_iface.go @@ -88,6 +88,7 @@ type AppIface interface { // ConvertUserToBot converts a user to bot. ConvertUserToBot(rctx request.CTX, user *model.User) (*model.Bot, *model.AppError) // Create/ Update a subscription history event + // This function is run daily to record the number of activated users in the system for Cloud workspaces SendSubscriptionHistoryEvent(userID string) (*model.SubscriptionHistory, error) // CreateBot creates the given bot and corresponding user. CreateBot(rctx request.CTX, bot *model.Bot) (*model.Bot, *model.AppError) diff --git a/server/channels/app/cloud.go b/server/channels/app/cloud.go index 9caf7a3bc8..24dc47235a 100644 --- a/server/channels/app/cloud.go +++ b/server/channels/app/cloud.go @@ -19,6 +19,7 @@ func (a *App) AdjustInProductLimits(limits *model.ProductLimits, subscription *m } // Create/ Update a subscription history event +// This function is run daily to record the number of activated users in the system for Cloud workspaces func (a *App) SendSubscriptionHistoryEvent(userID string) (*model.SubscriptionHistory, error) { license := a.Srv().License() @@ -27,10 +28,10 @@ func (a *App) SendSubscriptionHistoryEvent(userID string) (*model.SubscriptionHi return nil, nil } - // Get user count userCount, err := a.Srv().Store().User().Count(model.UserCountOptions{}) if err != nil { return nil, err } + return a.Cloud().CreateOrUpdateSubscriptionHistoryEvent(userID, int(userCount)) } diff --git a/server/channels/app/server.go b/server/channels/app/server.go index 93ebb04f59..4e9865673e 100644 --- a/server/channels/app/server.go +++ b/server/channels/app/server.go @@ -498,6 +498,7 @@ func NewServer(options ...Option) (*Server, error) { func (s *Server) runJobs() { s.runLicenseExpirationCheckJob() + s.Go(func() { appInstance := New(ServerConnector(s.Channels())) runDNDStatusExpireJob(appInstance) @@ -530,6 +531,9 @@ func (s *Server) runJobs() { s.Go(func() { runConfigCleanupJob(s) }) + s.Go(func() { + runCloudUserCountReportJob(s) + }) if complianceI := s.Channels().Compliance; complianceI != nil { go complianceI.StartComplianceDailyJob() @@ -1234,6 +1238,13 @@ func doSecurity(s *Server) { s.DoSecurityUpdateCheck() } +// Reports activated user count to the CWS every 24 hours +func runCloudUserCountReportJob(s *Server) { + model.CreateRecurringTask("Report user count for cloud subscription", func() { + s.doReportUserCountForCloudSubscriptionJob() + }, time.Hour*24) +} + func doTokenCleanup(s *Server) { expiry := model.GetMillis() - model.MaxTokenExipryTime @@ -1334,6 +1345,26 @@ func (s *Server) sendLicenseUpForRenewalEmail(users map[string]*model.User, lice return nil } +func (s *Server) doReportUserCountForCloudSubscriptionJob() { + s.LoadLicense() + + if !s.License().IsCloud() { + return + } + + mlog.Debug("Reporting daily user count for cloud subscription.") + + appInstance := New(ServerConnector(s.Channels())) + + _, err := appInstance.SendSubscriptionHistoryEvent("") + + if err != nil { + mlog.Error("an error occurred during daily user count reporting", mlog.Err(err)) + } + + mlog.Debug("Daily user count reported for cloud subscription.") +} + func (s *Server) doLicenseExpirationCheck() { s.LoadLicense() diff --git a/server/channels/app/user.go b/server/channels/app/user.go index fb84335464..d6a70a38e6 100644 --- a/server/channels/app/user.go +++ b/server/channels/app/user.go @@ -319,20 +319,6 @@ func (a *App) createUserOrGuest(c request.CTX, user *model.User, guest bool) (*m }, plugin.UserHasBeenCreatedID) }) - // For cloud yearly subscriptions, if the current user count of the workspace exceeds the number of seats initially purchased - // (plus the “threshold” of 10%), then a subscriptionHistoryEvent object would need to be created and added to the subscriptionHistory - // table in CWS. This is then used to calculate how much the customers have to pay in addition for the extra users. If the - // workspace is currently on a monthly plan, then this function will not do anything. - - if a.Channels().License().IsCloud() && !ruser.IsRemote() { - go func(userId string) { - _, err := a.SendSubscriptionHistoryEvent(userId) - if err != nil { - c.Logger().Error("Failed to create/update the SubscriptionHistoryEvent", mlog.Err(err)) - } - }(ruser.Id) - } - userLimits, limitErr := a.GetServerLimits() if limitErr != nil { // we don't want to break the create user flow just because of this. @@ -1355,15 +1341,6 @@ func (a *App) UpdateUser(c request.CTX, user *model.User, sendNotifications bool a.InvalidateCacheForUser(user.Id) a.onUserProfileChange(user.Id) - if a.Channels().License().IsCloud() && prev.IsRemote() && !user.IsRemote() { - go func(userId string) { - _, err := a.SendSubscriptionHistoryEvent(userId) - if err != nil { - c.Logger().Error("Failed to create/update the SubscriptionHistoryEvent", mlog.Err(err)) - } - }(user.Id) - } - newUser.Sanitize(map[string]bool{}) return newUser, nil