From 3d559159f04017b2b0b91a68b5a2da610b7bb109 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Thu, 4 Jun 2020 14:46:49 +0200 Subject: [PATCH] Allow notification apps to defer and flush the sending Signed-off-by: Joas Schilling --- lib/composer/composer/autoload_classmap.php | 1 + lib/composer/composer/autoload_static.php | 1 + lib/private/Notification/Manager.php | 44 +++++++++++++++++++ lib/public/Notification/IDeferrableApp.php | 48 +++++++++++++++++++++ lib/public/Notification/IManager.php | 17 ++++++++ 5 files changed, 111 insertions(+) create mode 100644 lib/public/Notification/IDeferrableApp.php diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index b51c9876e5d..f9ab1ebb2de 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -408,6 +408,7 @@ return array( 'OCP\\Notification\\AlreadyProcessedException' => $baseDir . '/lib/public/Notification/AlreadyProcessedException.php', 'OCP\\Notification\\IAction' => $baseDir . '/lib/public/Notification/IAction.php', 'OCP\\Notification\\IApp' => $baseDir . '/lib/public/Notification/IApp.php', + 'OCP\\Notification\\IDeferrableApp' => $baseDir . '/lib/public/Notification/IDeferrableApp.php', 'OCP\\Notification\\IDismissableNotifier' => $baseDir . '/lib/public/Notification/IDismissableNotifier.php', 'OCP\\Notification\\IManager' => $baseDir . '/lib/public/Notification/IManager.php', 'OCP\\Notification\\INotification' => $baseDir . '/lib/public/Notification/INotification.php', diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php index 2f640e014f3..86e143fa257 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -437,6 +437,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OCP\\Notification\\AlreadyProcessedException' => __DIR__ . '/../../..' . '/lib/public/Notification/AlreadyProcessedException.php', 'OCP\\Notification\\IAction' => __DIR__ . '/../../..' . '/lib/public/Notification/IAction.php', 'OCP\\Notification\\IApp' => __DIR__ . '/../../..' . '/lib/public/Notification/IApp.php', + 'OCP\\Notification\\IDeferrableApp' => __DIR__ . '/../../..' . '/lib/public/Notification/IDeferrableApp.php', 'OCP\\Notification\\IDismissableNotifier' => __DIR__ . '/../../..' . '/lib/public/Notification/IDismissableNotifier.php', 'OCP\\Notification\\IManager' => __DIR__ . '/../../..' . '/lib/public/Notification/IManager.php', 'OCP\\Notification\\INotification' => __DIR__ . '/../../..' . '/lib/public/Notification/INotification.php', diff --git a/lib/private/Notification/Manager.php b/lib/private/Notification/Manager.php index 3a19b0f49e6..f485b37cae7 100644 --- a/lib/private/Notification/Manager.php +++ b/lib/private/Notification/Manager.php @@ -31,6 +31,7 @@ use OCP\AppFramework\QueryException; use OCP\ILogger; use OCP\Notification\AlreadyProcessedException; use OCP\Notification\IApp; +use OCP\Notification\IDeferrableApp; use OCP\Notification\IDismissableNotifier; use OCP\Notification\IManager; use OCP\Notification\INotification; @@ -55,6 +56,8 @@ class Manager implements IManager { /** @var bool */ protected $preparingPushNotification; + /** @var bool */ + protected $deferPushing; public function __construct(IValidator $validator, ILogger $logger) { @@ -65,6 +68,7 @@ class Manager implements IManager { $this->appClasses = []; $this->notifierClasses = []; $this->preparingPushNotification = false; + $this->deferPushing = false; } /** * @param string $appClass The service must implement IApp, otherwise a @@ -199,6 +203,46 @@ class Manager implements IManager { return $this->preparingPushNotification; } + /** + * The calling app should only "flush" when it got returned true on the defer call + * @return bool + * @since 20.0.0 + */ + public function defer(): bool { + $alreadyDeferring = $this->deferPushing; + $this->deferPushing = true; + + $apps = $this->getApps(); + + foreach ($apps as $app) { + if ($app instanceof IDeferrableApp) { + $app->defer(); + } + } + + return !$alreadyDeferring; + } + + /** + * @since 20.0.0 + */ + public function flush(): void { + $apps = $this->getApps(); + + foreach ($apps as $app) { + if (!$app instanceof IDeferrableApp) { + continue; + } + + try { + $app->flush(); + } catch (\InvalidArgumentException $e) { + } + } + + $this->deferPushing = false; + } + /** * @param INotification $notification * @throws \InvalidArgumentException When the notification is not valid diff --git a/lib/public/Notification/IDeferrableApp.php b/lib/public/Notification/IDeferrableApp.php new file mode 100644 index 00000000000..48ae7574192 --- /dev/null +++ b/lib/public/Notification/IDeferrableApp.php @@ -0,0 +1,48 @@ + + * + * @author Joas Schilling + * + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see + * + */ + +namespace OCP\Notification; + +/** + * Interface IDeferrableApp + * + * @package OCP\Notification + * @since 20.0.0 + */ +interface IDeferrableApp extends IApp { + /** + * Start deferring notifications until `flush()` is called + * + * @since 20.0.0 + */ + public function defer(): void; + + /** + * Send all deferred notifications that have been stored since `defer()` was called + * + * @since 20.0.0 + */ + public function flush(): void; +} diff --git a/lib/public/Notification/IManager.php b/lib/public/Notification/IManager.php index 4acfa7ce786..dfc94c0be80 100644 --- a/lib/public/Notification/IManager.php +++ b/lib/public/Notification/IManager.php @@ -91,4 +91,21 @@ interface IManager extends IApp, INotifier { * @since 18.0.0 */ public function dismissNotification(INotification $notification): void; + + /** + * Start deferring notifications until `flush()` is called + * + * The calling app should only "flush" when it got returned true on the defer call, + * otherwise another app is deferring the sending already. + * @return bool + * @since 20.0.0 + */ + public function defer(): bool; + + /** + * Send all deferred notifications that have been stored since `defer()` was called + * + * @since 20.0.0 + */ + public function flush(): void; } -- 2.39.5