Skip to content

Commit 4e7d562

Browse files
committed
Reorganize how deletes are deferred so we can properly group them
Signed-off-by: Joas Schilling <coding@schilljs.com>
1 parent 77be7fd commit 4e7d562

File tree

3 files changed

+57
-19
lines changed

3 files changed

+57
-19
lines changed

lib/App.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ public function markProcessed(INotification $notification): void {
8282
}
8383
foreach ($deleted as $user => $notifications) {
8484
foreach ($notifications as $data) {
85-
$this->push->pushDeleteToDevice((string) $user, $data['id'], $data['app']);
85+
$this->push->pushDeleteToDevice((string) $user, [$data['id']], $data['app']);
8686
}
8787
}
8888
if (!$isAlreadyDeferring) {

lib/Controller/EndpointController.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ public function deleteNotification(int $id): DataResponse {
185185
$deleted = $this->handler->deleteById($id, $this->getCurrentUser(), $notification);
186186

187187
if ($deleted) {
188-
$this->push->pushDeleteToDevice($this->getCurrentUser(), $id, $notification->getApp());
188+
$this->push->pushDeleteToDevice($this->getCurrentUser(), [$id], $notification->getApp());
189189
}
190190
} catch (NotificationNotFoundException $e) {
191191
}

lib/Push.php

Lines changed: 55 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ class Push {
7979
protected $deferPayloads = false;
8080
/** @var array[] */
8181
protected $deletesToPush = [];
82+
/** @var string[] */
83+
protected $deleteAllsToPush = [];
8284
/** @var INotification[] */
8385
protected $notificationsToPush = [];
8486

@@ -170,12 +172,18 @@ public function flushPayloads(): void {
170172
$this->notificationsToPush = [];
171173
}
172174

175+
if (!empty($this->deleteAllsToPush)) {
176+
foreach ($this->deleteAllsToPush as $userId) {
177+
$this->pushDeleteToDevice($userId, null);
178+
}
179+
$this->deleteAllsToPush = [];
180+
}
181+
173182
if (!empty($this->deletesToPush)) {
174-
// Check for $id = 0 then only trigger delete all for that user
175-
// Otherwise group by "app" (['spreed', 'talk', 'admin_notification_talk'] OR not!)
176-
// And trigger each chunk per user
177-
foreach ($this->deletesToPush as $id => $data) {
178-
$this->pushDeleteToDevice($data['userId'], $id, $data['app']);
183+
foreach ($this->deletesToPush as $userId => $data) {
184+
foreach ($data as $client => $notificationIds) {
185+
$this->pushDeleteToDevice($userId, $notificationIds, $client);
186+
}
179187
}
180188
$this->deletesToPush = [];
181189
}
@@ -313,21 +321,47 @@ public function pushToDevice(int $id, INotification $notification, ?OutputInterf
313321
}
314322
}
315323

316-
public function pushDeleteToDevice(string $userId, ?int $notificationId, string $app = ''): void {
324+
/**
325+
* @param string $userId
326+
* @param ?int[] $notificationIds
327+
* @param string $app
328+
* @throws InvalidTokenException FIXME investigate
329+
*/
330+
public function pushDeleteToDevice(string $userId, ?array $notificationIds, string $app = ''): void {
317331
if (!$this->config->getSystemValueBool('has_internet_connection', true)) {
318332
return;
319333
}
320334

321335
if ($this->deferPreparing) {
322-
if ($notificationId === null) {
323-
$notificationId = 0;
336+
if ($notificationIds === null) {
337+
$this->deleteAllsToPush[$userId] = true;
338+
if (isset($this->deletesToPush[$userId])) {
339+
unset($this->deletesToPush[$userId]);
340+
}
341+
} else {
342+
if (isset($this->deleteAllsToPush[$userId])) {
343+
return;
344+
}
345+
346+
$isTalkNotification = \in_array($app, ['spreed', 'talk', 'admin_notification_talk'], true);
347+
$clientGroup = $isTalkNotification ? 'talk' : 'files';
348+
349+
if (!isset($this->deletesToPush[$userId])) {
350+
$this->deletesToPush[$userId] = [];
351+
}
352+
if (!isset($this->deletesToPush[$userId][$clientGroup])) {
353+
$this->deletesToPush[$userId][$clientGroup] = [];
354+
}
355+
356+
foreach ($notificationIds as $notificationId) {
357+
$this->deletesToPush[$userId][$clientGroup][] = $notificationId;
358+
}
324359
}
325-
$this->deletesToPush[$notificationId] = ['userId' => $userId, 'app' => $app]; // FIXME this assumes there is only 1 delete-all per request
326360
$this->loadDevicesForUsers[] = $userId;
327361
return;
328362
}
329363

330-
$deleteAll = $notificationId !== null;
364+
$deleteAll = $notificationIds === null;
331365

332366
$user = $this->createFakeUserObject($userId);
333367

@@ -358,17 +392,21 @@ public function pushDeleteToDevice(string $userId, ?int $notificationId, string
358392
}
359393

360394
try {
361-
if ($deleteAll) {
362-
$payload = json_encode($this->encryptAndSignDelete($userKey, $device, null));
363-
} else {
364-
$payload = json_encode($this->encryptAndSignDelete($userKey, $device, [$notificationId]));
365-
}
366-
367395
$proxyServer = rtrim($device['proxyserver'], '/');
368396
if (!isset($this->payloadsToSend[$proxyServer])) {
369397
$this->payloadsToSend[$proxyServer] = [];
370398
}
371-
$this->payloadsToSend[$proxyServer][] = $payload;
399+
400+
if ($deleteAll) {
401+
$data = $this->encryptAndSignDelete($userKey, $device, null);
402+
$this->payloadsToSend[$proxyServer][] = json_encode($data['payload']);
403+
} else {
404+
while (!empty($notificationIds)) {
405+
$data = $this->encryptAndSignDelete($userKey, $device, $notificationIds);
406+
$notificationIds = $data['remaining'];
407+
$this->payloadsToSend[$proxyServer][] = json_encode($data['payload']);
408+
}
409+
}
372410
} catch (\InvalidArgumentException $e) {
373411
// Failed to encrypt message for device: public key is invalid
374412
$this->deletePushToken($device['token']);

0 commit comments

Comments
 (0)