1
0
Fork 0

Compare commits

..

2 commits

Author SHA1 Message Date
Jonathan Treffler
f0e9043519
Update lib/Listener/CalendarListener.php
Co-authored-by: Richard Steinmetz <richard@steinmetz.cloud>
2024-09-17 19:40:56 +02:00
Jonathan Treffler
e2805beb16 switch to GuzzleHttp for web push transport, parallelize notification sending 2024-09-14 16:52:54 +02:00
4 changed files with 32 additions and 21 deletions

View file

@ -10,14 +10,15 @@ Watch the video (YouTube):
# Nextcloud extension for WebDAV-Push
`nc_ext_dav_push` is a [Nextcloud](https://github.com/nextcloud/server) extension to demonstrate [WebDAV-Push](https://github.com/bitfireAT/webdav-push/) support on calendars (address books are not supported yet).
`nc_ext_dav_push` is a [Nextcloud](https://github.com/nextcloud/server) extension to demonstrate [WebDAV-Push](https://github.com/bitfireAT/webdav-push/) support on calendars/address books.
It is the server part of our efforts to draft a WebDAV-Push standard and provide a working implementation (server + client) in order to demonstrate it.
> [!WARNING]
> This extension is in an early stage of development. It is for demonstration and testing purposes only. Don't use it on production systems!
**This extension is in a very early stage of development. It is for demonstration and testing purposes only. Don't use it on production systems!**
For instance, push subscriptions currently don't expire and won't be removed when they have become invalid. So the table will grow bigger and bigger and everything will become slow over time. You can however install/enable the extension to test it and disable or remove it again at any time. When the extension is disabled, it doesn't influence your system.
For instance, push subscriptions currently don't expire, can't be deleted by clients and won't be removed when they have become invalid. So the table will grow bigger and bigger and everything will become slow over time.
You can however install/enable the extension to test it and disable or remove it again at any time. When the extension is disabled, it doesn't influence your system.
## About WebDAV-Push

View file

@ -37,6 +37,7 @@ use OCA\DAV\Events\CardDeletedEvent;
use OCA\DAV\Events\CardUpdatedEvent;
use Psr\Log\LoggerInterface;
use GuzzleHttp\Promise;
use OCA\DavPush\Service\SubscriptionService;
use OCA\DavPush\Transport\TransportManager;
@ -59,13 +60,16 @@ class CalendarListener implements IEventListener {
$collectionName = $event->getCalendarData()['uri'];
$subscriptions = $this->subscriptionService->findAll($collectionName);
$notificationPromises = (function () use ($collectionName, $subscriptions): \Generator {
foreach($subscriptions as $subscription) {
$transport = $this->transportManager->getTransport($subscription->getTransport());
try {
$transport->notify($subscription->getUserId(), $collectionName, $subscription->getId());
} catch (\Exception $e) {
$this->logger->error("transport " . $subscription->getTransport() . " failed to deliver notification to subscription " . $subscription->getId());
}
}
yield $transport->notify($subscription->getUserId(), $collectionName, $subscription->getId());
}
})();
$responses = Promise\Utils::settle($notificationPromises)->wait();
// TODO: iterate over responses and log errors
// $this->logger->error("transport " . $subscription->getTransport() . " failed to deliver notification to subscription " . $subscription->getId());
}
}

View file

@ -30,6 +30,9 @@ use OCA\DavPush\Transport\Transport;
use OCA\DavPush\Service\WebPushSubscriptionService;
use OCA\DavPush\Errors\WebPushSubscriptionNotFound;
use OCP\Http\Client\IClientService;
use OCP\Http\Client\IPromise;
use Sabre\Xml\Service;
class WebPushTransport extends Transport {
@ -37,6 +40,7 @@ class WebPushTransport extends Transport {
public function __construct(
private WebPushSubscriptionService $webPushSubscriptionService,
private IClientService $httpClientService
) {}
private function parseOptions(array $options): array {
@ -79,7 +83,7 @@ class WebPushTransport extends Transport {
];
}
public function notify(string $userId, string $collectionName, int $subscriptionId) {
public function notify(string $userId, string $collectionName, int $subscriptionId): IPromise {
$xmlService = new Service();
$pushResource = $this->webPushSubscriptionService->findBySubscriptionId($subscriptionId)->getPushResource();
@ -88,15 +92,15 @@ class WebPushTransport extends Transport {
'{DAV:Push}topic' => $collectionName,
]);
$options = [
'http' => [
'method' => 'POST',
'content' => $content,
],
];
$httpClient = $this->httpClientService->newClient();
$context = stream_context_create($options);
$result = file_get_contents($pushResource, false, $context);
return $httpClient->postAsync($pushResource, [
"body" => $content,
"timeout" => 10,
"headers" => [
"Content-Type" => "application/xml",
],
]);
}
public function getSubscriptionIdFromOptions(string $userId, string $collectionName, $options): ?int {

View file

@ -26,6 +26,8 @@ declare(strict_types=1);
namespace OCA\DavPush\Transport;
use OCP\Http\Client\IPromise;
abstract class Transport {
protected $id;
@ -69,5 +71,5 @@ abstract class Transport {
// Change mutable options of the subscription (if any exist)
abstract public function updateSubscription($subsciptionId, $options);
abstract public function notify(string $userId, string $collectionName, int $subscriptionId);
abstract public function notify(string $userId, string $collectionName, int $subscriptionId): IPromise;
}