From f4f0f32468340ec1b678fecfaf43712e0ef4c628 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Wed, 24 Feb 2021 13:19:46 +0100 Subject: [PATCH] add realtime event --- app/controllers/shared/api.php | 11 ++- app/init.php | 5 ++ src/Appwrite/Event/Realtime.php | 136 ++++++++++++++++++++++++++++++++ 3 files changed, 150 insertions(+), 2 deletions(-) create mode 100644 src/Appwrite/Event/Realtime.php diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index 8dc0c097c..e6ab3b40f 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -110,7 +110,7 @@ App::init(function ($utopia, $request, $response, $project, $user, $register, $e }, ['utopia', 'request', 'response', 'project', 'user', 'register', 'events', 'audits', 'usage', 'deletes'], 'api'); -App::shutdown(function ($utopia, $request, $response, $project, $events, $audits, $usage, $deletes, $mode) { +App::shutdown(function ($utopia, $request, $response, $project, $events, $audits, $usage, $deletes, $realtime, $mode) { /** @var Utopia\App $utopia */ /** @var Utopia\Swoole\Request $request */ /** @var Appwrite\Utopia\Response $response */ @@ -119,6 +119,7 @@ App::shutdown(function ($utopia, $request, $response, $project, $events, $audits /** @var Appwrite\Event\Event $audits */ /** @var Appwrite\Event\Event $usage */ /** @var Appwrite\Event\Event $deletes */ + /** @var Appwrite\Event\Realtime $realtime */ /** @var Appwrite\Event\Event $functions */ /** @var bool $mode */ @@ -139,6 +140,12 @@ App::shutdown(function ($utopia, $request, $response, $project, $events, $audits ->setQueue('v1-functions') ->setClass('FunctionsV1') ->trigger(); + + $realtime + ->setEvent($events->getParam('event')) + ->setPayload($response->getPayload()) + ->trigger(); + } if (!empty($audits->getParam('event'))) { @@ -162,4 +169,4 @@ App::shutdown(function ($utopia, $request, $response, $project, $events, $audits ; } -}, ['utopia', 'request', 'response', 'project', 'events', 'audits', 'usage', 'deletes', 'mode'], 'api'); +}, ['utopia', 'request', 'response', 'project', 'events', 'audits', 'usage', 'deletes', 'realtime', 'mode'], 'api'); diff --git a/app/init.php b/app/init.php index a19b9c0e0..a4d2914b0 100644 --- a/app/init.php +++ b/app/init.php @@ -20,6 +20,7 @@ use Appwrite\Database\Adapter\Redis as RedisAdapter; use Appwrite\Database\Document; use Appwrite\Database\Validator\Authorization; use Appwrite\Event\Event; +use Appwrite\Event\Realtime; use Appwrite\Extend\PDO; use Appwrite\OpenSSL\OpenSSL; use Utopia\App; @@ -321,6 +322,10 @@ App::setResource('events', function($register) { return new Event('', ''); }, ['register']); +App::setResource('realtime', function($register) { + return new Realtime('', []); +}, ['register']); + App::setResource('audits', function($register) { return new Event(Event::AUDITS_QUEUE_NAME, Event::AUDITS_CLASS_NAME); }, ['register']); diff --git a/src/Appwrite/Event/Realtime.php b/src/Appwrite/Event/Realtime.php new file mode 100644 index 000000000..e1f1f887f --- /dev/null +++ b/src/Appwrite/Event/Realtime.php @@ -0,0 +1,136 @@ +event = $event; + $this->payload = new Document($payload); + } + + /** + * @param string $event + * return $this + */ + public function setEvent(string $event): self + { + $this->event = $event; + return $this; + } + + /** + * @return string + */ + public function getEvent(): string + { + return $this->event; + } + + /** + * @param array $payload + * return $this + */ + public function setPayload(array $payload): self + { + $this->payload = new Document($payload); + return $this; + } + + /** + * @return Document + */ + public function getPayload(): Document + { + return $this->payload; + } + + /** + * Populate channels array based on the event name and payload. + * + * @return void + */ + private function prepareChannels(): void + { + switch (true) { + case strpos($this->event, 'account.') === 0: + $this->channels[] = 'account.' . $this->payload->getId(); + + break; + case strpos($this->event, 'database.collections.') === 0: + $this->channels[] = 'collections'; + $this->channels[] = 'collections.' . $this->payload->getId(); + + break; + case strpos($this->event, 'database.documents.') === 0: + $this->channels[] = 'documents'; + $this->channels[] = 'collections.' . $this->payload->getAttribute('$collection') . '.documents'; + $this->channels[] = 'documents.' . $this->payload->getId(); + + break; + case strpos($this->event, 'storage.') === 0: + $this->channels[] = 'files'; + $this->channels[] = 'files.' . $this->payload->getId(); + + break; + } + } + + /** + * Execute Event. + * + * @return void + */ + public function trigger(): void + { + $this->prepareChannels(); + if (empty($this->channels)) return; + + $redis = new \Redis(); + $redis->connect(App::getEnv('_APP_REDIS_HOST', ''), App::getEnv('_APP_REDIS_PORT', '')); + $redis->publish('realtime', json_encode([ + 'channels' => $this->channels, + 'data' => [ + 'event' => $this->event, + 'timestamp' => time(), + 'payload' => $this->payload + ] + ])); + + $this->reset(); + } + + public function reset(): self + { + $this->event = ''; + $this->payload = $this->channels = []; + + return $this; + } +}