From 02cb8d9f2651a5668456547f8c7f862fa226bc5b Mon Sep 17 00:00:00 2001 From: theronakpatel Date: Mon, 8 Dec 2025 12:54:14 +0530 Subject: [PATCH 1/5] reduce memory usage by avoiding the UserManager's local cache --- .../RecoveryWarningNotificationCommand.php | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/lib/Command/RecoveryWarningNotificationCommand.php b/lib/Command/RecoveryWarningNotificationCommand.php index 0a6f0d2..4c9a893 100644 --- a/lib/Command/RecoveryWarningNotificationCommand.php +++ b/lib/Command/RecoveryWarningNotificationCommand.php @@ -159,6 +159,26 @@ class RecoveryWarningNotificationCommand extends Command { } + /** + * Get user object without caching to avoid memory accumulation + * Uses getBackends to walk through all backends and get user with caching disabled + * + * @param string $username The username to retrieve + * @return \OCP\IUser|null The user object or null if not found + */ + private function getUserWithoutCache(string $username) { + $backends = $this->userManager->getBackends(); + + foreach ($backends as $backend) { + if ($backend->userExists($username)) { + // Use getUserObject with cacheUser = false to avoid caching + // This prevents the user object from being stored in the manager's cache + return $this->userManager->getUserObject($username, $backend, false); + } + } + + return null; + } private function identifyUnverifiedUsers(OutputInterface $output): void { $users = $this->config->getUsersForUserValue(Application::APP_ID, 'recovery-email', ''); @@ -181,7 +201,7 @@ class RecoveryWarningNotificationCommand extends Command { foreach ($users as $username) { try { - $user = $this->userManager->get($username); + $user = $this->getUserWithoutCache($username); if (!$user) { $invalidCount++; -- GitLab From 0b62b8ea750367ecebfba6d18d9c4fe0edc34612 Mon Sep 17 00:00:00 2001 From: theronakpatel Date: Mon, 8 Dec 2025 12:59:06 +0530 Subject: [PATCH 2/5] Don't create the disable and delete lists if the option is not set --- .../RecoveryWarningNotificationCommand.php | 38 ++++++++++++++----- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/lib/Command/RecoveryWarningNotificationCommand.php b/lib/Command/RecoveryWarningNotificationCommand.php index 4c9a893..477b6dc 100644 --- a/lib/Command/RecoveryWarningNotificationCommand.php +++ b/lib/Command/RecoveryWarningNotificationCommand.php @@ -123,11 +123,16 @@ class RecoveryWarningNotificationCommand extends Command { // Initialize arrays $this->uids = []; - $this->disableUids = []; - $this->deleteUids = []; + // Only initialize disable/delete arrays if the options are set + if ($disableAccounts) { + $this->disableUids = []; + } + if ($deleteAccounts) { + $this->deleteUids = []; + } // Process users - $this->identifyUnverifiedUsers($output); + $this->identifyUnverifiedUsers($output, $disableAccounts, $deleteAccounts); $this->sendNotificationsAndEmails($output); if ($disableAccounts) { @@ -143,8 +148,12 @@ class RecoveryWarningNotificationCommand extends Command { $output->writeln('[' . $endTime . '] === Command Summary ==='); $output->writeln(' - Users for notifications: ' . count($this->uids)); - $output->writeln(' - Users for disable: ' . count($this->disableUids)); - $output->writeln(' - Users for deletion: ' . count($this->deleteUids)); + if ($disableAccounts) { + $output->writeln(' - Users for disable: ' . count($this->disableUids)); + } + if ($deleteAccounts) { + $output->writeln(' - Users for deletion: ' . count($this->deleteUids)); + } $output->writeln(' - Total execution time: ' . round($overallDuration, 2) . 's'); $output->writeln('[' . $endTime . '] Recovery warning notification command completed successfully.'); @@ -180,7 +189,7 @@ class RecoveryWarningNotificationCommand extends Command { return null; } - private function identifyUnverifiedUsers(OutputInterface $output): void { + private function identifyUnverifiedUsers(OutputInterface $output, bool $checkDisable = false, bool $checkDelete = false): void { $users = $this->config->getUsersForUserValue(Application::APP_ID, 'recovery-email', ''); if (!is_array($users)) { $output->writeln('Error: Expected array for recovery-email users, got ' . gettype($users) . ''); @@ -260,8 +269,13 @@ class RecoveryWarningNotificationCommand extends Command { $this->uids[] = $uid; } - $this->identifyForDisable($user, $age); - $this->identifyForDelete($user, $age); + // Only check for disable/delete if the options are set + if ($checkDisable) { + $this->identifyForDisable($user, $age); + } + if ($checkDelete) { + $this->identifyForDelete($user, $age); + } $disabledAtTimestamp = strtotime($existingDisableDate); $deleteDate = date('Y-m-d', $disabledAtTimestamp + ($this->deleteUserAfterDisableDays * 24 * 60 * 60)); @@ -292,8 +306,12 @@ class RecoveryWarningNotificationCommand extends Command { $output->writeln(' - Invalid: ' . $invalidCount); $output->writeln(' - Errors: ' . $errorCount); $output->writeln(' - For notifications: ' . count($this->uids)); - $output->writeln(' - For disable: ' . count($this->disableUids)); - $output->writeln(' - For deletion: ' . count($this->deleteUids)); + if ($checkDisable) { + $output->writeln(' - For disable: ' . count($this->disableUids)); + } + if ($checkDelete) { + $output->writeln(' - For deletion: ' . count($this->deleteUids)); + } } private function identifyForDisable($user, int $age): void { -- GitLab From d9fd2074f53b509925e07c5bf132cf0d240a7972 Mon Sep 17 00:00:00 2001 From: theronakpatel Date: Mon, 8 Dec 2025 13:21:02 +0530 Subject: [PATCH 3/5] lint --- lib/Command/RecoveryWarningNotificationCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Command/RecoveryWarningNotificationCommand.php b/lib/Command/RecoveryWarningNotificationCommand.php index 477b6dc..6379730 100644 --- a/lib/Command/RecoveryWarningNotificationCommand.php +++ b/lib/Command/RecoveryWarningNotificationCommand.php @@ -171,7 +171,7 @@ class RecoveryWarningNotificationCommand extends Command { /** * Get user object without caching to avoid memory accumulation * Uses getBackends to walk through all backends and get user with caching disabled - * + * * @param string $username The username to retrieve * @return \OCP\IUser|null The user object or null if not found */ -- GitLab From c349fd079a0424b95d5cca75498567b557a7debe Mon Sep 17 00:00:00 2001 From: theronakpatel Date: Mon, 8 Dec 2025 13:31:43 +0530 Subject: [PATCH 4/5] lint --- lib/Command/RecoveryWarningNotificationCommand.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/Command/RecoveryWarningNotificationCommand.php b/lib/Command/RecoveryWarningNotificationCommand.php index 6379730..551edf4 100644 --- a/lib/Command/RecoveryWarningNotificationCommand.php +++ b/lib/Command/RecoveryWarningNotificationCommand.php @@ -190,6 +190,8 @@ class RecoveryWarningNotificationCommand extends Command { } private function identifyUnverifiedUsers(OutputInterface $output, bool $checkDisable = false, bool $checkDelete = false): void { + $identificationStart = microtime(true); + $users = $this->config->getUsersForUserValue(Application::APP_ID, 'recovery-email', ''); if (!is_array($users)) { $output->writeln('Error: Expected array for recovery-email users, got ' . gettype($users) . ''); @@ -298,6 +300,8 @@ class RecoveryWarningNotificationCommand extends Command { } } + $identificationDuration = microtime(true) - $identificationStart; + $output->writeln('User processing summary:'); $output->writeln(' - Total users: ' . count($users)); $output->writeln(' - Processed: ' . $processedCount); @@ -312,6 +316,7 @@ class RecoveryWarningNotificationCommand extends Command { if ($checkDelete) { $output->writeln(' - For deletion: ' . count($this->deleteUids)); } + $output->writeln(' - Identification time: ' . round($identificationDuration, 2) . 's'); } private function identifyForDisable($user, int $age): void { -- GitLab From 4e0cb7c8a96c5ec60a31518c2b46bc9328fa004f Mon Sep 17 00:00:00 2001 From: theronakpatel Date: Mon, 8 Dec 2025 17:26:19 +0530 Subject: [PATCH 5/5] getUser --- lib/Command/RecoveryWarningNotificationCommand.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/Command/RecoveryWarningNotificationCommand.php b/lib/Command/RecoveryWarningNotificationCommand.php index 551edf4..4c78bd1 100644 --- a/lib/Command/RecoveryWarningNotificationCommand.php +++ b/lib/Command/RecoveryWarningNotificationCommand.php @@ -171,11 +171,11 @@ class RecoveryWarningNotificationCommand extends Command { /** * Get user object without caching to avoid memory accumulation * Uses getBackends to walk through all backends and get user with caching disabled - * + * * @param string $username The username to retrieve * @return \OCP\IUser|null The user object or null if not found */ - private function getUserWithoutCache(string $username) { + private function getUser(string $username) { $backends = $this->userManager->getBackends(); foreach ($backends as $backend) { @@ -212,7 +212,7 @@ class RecoveryWarningNotificationCommand extends Command { foreach ($users as $username) { try { - $user = $this->getUserWithoutCache($username); + $user = $this->getUser($username); if (!$user) { $invalidCount++; -- GitLab