From ba2ae29e3aac8eddf560e0254655cd69dbe4b28f Mon Sep 17 00:00:00 2001 From: mngshm Date: Tue, 11 Mar 2025 17:10:03 +0530 Subject: [PATCH] [server](StorageExceedingAlerts) struct to loop through slices of set of users depending on storage consumed --- server/cmd/museum/main.go | 4 +- .../controller/email/email_notification.go | 75 +++++++++++++------ server/pkg/repo/user.go | 4 +- 3 files changed, 56 insertions(+), 27 deletions(-) diff --git a/server/cmd/museum/main.go b/server/cmd/museum/main.go index 0780022ccf..e23a2516dc 100644 --- a/server/cmd/museum/main.go +++ b/server/cmd/museum/main.go @@ -980,9 +980,8 @@ func setupAndStartCrons(userAuthRepo *repo.UserAuthRepository, publicCollectionR _ = castDb.DeleteUnclaimedCodes(context.Background(), timeUtil.MicrosecondsBeforeMinutes(60)) dataCleanupCtrl.DeleteDataCron() }) - schedule(c, "@every 24h", func() { - emailNotificationCtrl.SendStorageLimitExceededMails() + emailNotificationCtrl.SendStorageAlerts() }) schedule(c, "@every 1m", func() { @@ -1003,6 +1002,7 @@ func setupAndStartCrons(userAuthRepo *repo.UserAuthRepository, publicCollectionR }) c.Start() + log.Infoln(c.Entry(17).Next) } func cors() gin.HandlerFunc { diff --git a/server/pkg/controller/email/email_notification.go b/server/pkg/controller/email/email_notification.go index f2178221f8..e0eb361310 100644 --- a/server/pkg/controller/email/email_notification.go +++ b/server/pkg/controller/email/email_notification.go @@ -166,7 +166,7 @@ func (c *EmailNotificationController) OnSubscriptionCancelled(userID int64) { } } -func (c *EmailNotificationController) SendStorageLimitExceededMails() { +func (c *EmailNotificationController) SendStorageAlerts() { if c.isSendingStorageLimitExceededMails { log.Info("Skipping sending storage limit exceeded mails as another instance is still running") return @@ -179,30 +179,59 @@ func (c *EmailNotificationController) SendStorageLimitExceededMails() { return } defer c.LockController.ReleaseLock(StorageLimitExceededMailLock) - users, err := c.UserRepo.GetUsersWithIndividualPlanWhoHaveExceededStorageQuota() - if err != nil { - log.Error("Error while fetching user list", err) - return + + // Notifs struct gets the list of both the users who have consumed + // 90% storage and 100% of their subcriptions. Then, it ranges through + // the slices of the both the users and inside this for loop, users from + // both the slices are separately looped. This was done to avoid + // duplication of a lot of code if both the users were ranged inside a loop + // separately. + notifs := []struct { + getListofSubscribers func() ([]ente.User, error) + template string + subject string + }{ + { + getListofSubscribers: func() ([]ente.User, error) { + return c.UserRepo.GetUsersWithExceedingStorages(90) + }, + template: StorageLimitExceededTemplate, + subject: StorageLimitExceededTemplate, + }, + { + getListofSubscribers: func() ([]ente.User, error) { + return c.UserRepo.GetUsersWithExceedingStorages(100) + }, + template: StorageLimitExceededTemplate, + subject: StorageLimitExceededSubject, + }, } - for _, u := range users { - lastNotificationTime, err := c.NotificationHistoryRepo.GetLastNotificationTime(u.ID, StorageLimitExceededTemplateID) - logger := log.WithFields(log.Fields{ - "user_id": u.ID, - }) + for _, notification := range notifs { + users, err := notification.getListofSubscribers() if err != nil { - logger.Error("Could not fetch last notification time", err) + log.WithError(err).Error("Failed to get list of users") continue } - if lastNotificationTime > 0 { - continue + for _, u := range users { + lastNotificationTime, err := c.NotificationHistoryRepo.GetLastNotificationTime(u.ID, StorageLimitExceededTemplateID) + logger := log.WithFields(log.Fields{ + "user_id": u.ID, + }) + if err != nil { + logger.Error("Could not fetch last notification time", err) + continue + } + if lastNotificationTime > 0 { + continue + } + logger.Info("Alerting about storage limit exceeded") + err = email.SendTemplatedEmail([]string{u.Email}, "team@ente.io", "team@ente.io", notification.subject, notification.template, nil, nil) + if err != nil { + logger.Info("Error notifying", err) + continue + } + c.NotificationHistoryRepo.SetLastNotificationTimeToNow(u.ID, StorageLimitExceededTemplateID) } - logger.Info("Alerting about storage limit exceeded") - err = email.SendTemplatedEmail([]string{u.Email}, "team@ente.io", "team@ente.io", StorageLimitExceededSubject, StorageLimitExceededTemplate, nil, nil) - if err != nil { - logger.Info("Error notifying", err) - continue - } - c.NotificationHistoryRepo.SetLastNotificationTimeToNow(u.ID, StorageLimitExceededTemplateID) } } @@ -213,14 +242,14 @@ func (c *EmailNotificationController) setStorageLimitExceededMailerJobStatus(isS func (c *EmailNotificationController) SendFamilyNudgeEmail() error { subscribedUsers, subUsersErr := c.UserRepo.GetSubscribedUsersWithoutFamily() if subUsersErr != nil { - stacktrace.Propagate(subUsersErr, "Failed to get subscribers") + return stacktrace.Propagate(subUsersErr, "Failed to get subscribers") } batchSize := 100 totalSubUsers := len(subscribedUsers) logrus.Println(totalSubUsers) - for i := 0; i < totalSubUsers; i++ { + for i := range totalSubUsers { end := i + batchSize if end > totalSubUsers { end = totalSubUsers @@ -236,7 +265,7 @@ func (c *EmailNotificationController) SendFamilyNudgeEmail() error { break } - thirtyDays := 30 * t.Second + thirtyDays := 30 * 24 * t.Hour creationTime := t.Unix(0, user.CreationTime) timeSinceCreation := t.Since(creationTime) diff --git a/server/pkg/repo/user.go b/server/pkg/repo/user.go index f43dcc8ea3..9d4d79eb3f 100644 --- a/server/pkg/repo/user.go +++ b/server/pkg/repo/user.go @@ -319,8 +319,8 @@ func (repo *UserRepository) GetUsersWithExceedingStorages(percentageThreshold in INNER JOIN usage ON users.user_id = usage.user_id INNER JOIN subscriptions - ON users.user_id = subscriptions.user_id AND usage.storage_consumed >= (subscriptions.storage * $1 / 100.0) AND users.encrypted_email IS NOT NULL AND users.family_admin_id IS NULL; - }`, percentageThreshold) + ON users.user_id = subscriptions.user_id AND usage.storage_consumed >= (subscriptions.storage * $1 / 100.0) AND users.encrypted_email is not null AND users.family_admin_id is NULL; + `, percentageThreshold) if err != nil { return nil, stacktrace.Propagate(err, "") }