Implemented subscription logic
This commit is contained in:
@ -44,6 +44,16 @@ class Message
|
||||
return time() - $this->created;
|
||||
}
|
||||
|
||||
public function toString(): string
|
||||
{
|
||||
$msg = [];
|
||||
if ($this->type) $msg[] = "event: ".$this->type;
|
||||
if ($this->retry) $msg[] = "retry: ".$this->retry;
|
||||
if ($this->id) $msg[] = "id: ".$this->id;
|
||||
if ($this->data) $msg[] = "data: ".$this->data;
|
||||
return join("\n", $msg)."\n\n";
|
||||
}
|
||||
|
||||
public static function fromData(array $data): Message
|
||||
{
|
||||
return new Message(
|
||||
|
24
src/Broker/SseSubscriber.php
Normal file
24
src/Broker/SseSubscriber.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace NoccyLabs\Mercureact\Broker;
|
||||
|
||||
use React\Stream\WritableStreamInterface;
|
||||
|
||||
class SseSubscriber implements SubscriberInterface
|
||||
{
|
||||
public function __construct(
|
||||
private WritableStreamInterface $stream
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
public function deliver(Message $message): void
|
||||
{
|
||||
$this->stream->write($message->toString());
|
||||
}
|
||||
|
||||
public function isAuthorized(string $topics): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
10
src/Broker/SubscriberInterface.php
Normal file
10
src/Broker/SubscriberInterface.php
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace NoccyLabs\Mercureact\Broker;
|
||||
|
||||
interface SubscriberInterface
|
||||
{
|
||||
public function deliver(Message $message): void;
|
||||
|
||||
public function isAuthorized(string $topics): bool;
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace NoccyLabs\Mercureact\Broker;
|
||||
|
||||
use ArrayIterator;
|
||||
use Countable;
|
||||
use IteratorAggregate;
|
||||
use SplObjectStorage;
|
||||
use Traversable;
|
||||
|
||||
class SubscriptionList implements Countable, IteratorAggregate
|
||||
{
|
||||
|
||||
private array $subscriptions = [];
|
||||
|
||||
|
||||
|
||||
public function count(): int
|
||||
{
|
||||
return count($this->subscriptions);
|
||||
}
|
||||
|
||||
public function getIterator(): Traversable
|
||||
{
|
||||
return new ArrayIterator($this->subscriptions);
|
||||
}
|
||||
}
|
||||
|
@ -10,17 +10,19 @@ class Topic
|
||||
|
||||
/** @var string Topic name */
|
||||
private string $topic;
|
||||
|
||||
/** @var array<string,Message> */
|
||||
private array $messages = [];
|
||||
|
||||
/** @var int Creation unixtime */
|
||||
private int $created;
|
||||
|
||||
private SubscriptionList $subscribers;
|
||||
private SplObjectStorage $subscribers;
|
||||
|
||||
public function __construct(string $topic)
|
||||
{
|
||||
$this->topic = $topic;
|
||||
$this->subscribers = new SubscriptionList();
|
||||
$this->subscribers = new SplObjectStorage();
|
||||
$this->created = time();
|
||||
}
|
||||
|
||||
@ -31,8 +33,10 @@ class Topic
|
||||
foreach ($this->subscribers as $subscriber) {
|
||||
if ($message->private === true) {
|
||||
// TODO check subscriber access
|
||||
$subscriber->deliver($message);
|
||||
} else {
|
||||
// TODO deliver to subscriber
|
||||
$subscriber->deliver($message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -52,6 +56,16 @@ class Topic
|
||||
return count($this->subscribers);
|
||||
}
|
||||
|
||||
public function addSubscriber(SubscriberInterface $subscriber)
|
||||
{
|
||||
$this->subscribers->attach($subscriber);
|
||||
}
|
||||
|
||||
public function removeSubscriber(SubscriberInterface $subscriber)
|
||||
{
|
||||
$this->subscribers->detach($subscriber);
|
||||
}
|
||||
|
||||
/**
|
||||
* Garbage collect histry
|
||||
*
|
||||
|
@ -9,6 +9,12 @@ class TopicManager
|
||||
/** @var array<string,Topic> */
|
||||
private array $topics = [];
|
||||
|
||||
private SplObjectStorage $subscribers;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->subscribers = new SplObjectStorage();
|
||||
}
|
||||
|
||||
public function getTopic(string $topic): Topic
|
||||
{
|
||||
@ -25,6 +31,26 @@ class TopicManager
|
||||
}
|
||||
}
|
||||
|
||||
public function subscribe(SubscriberInterface $subscriber, array $topics): void
|
||||
{
|
||||
foreach ($topics as $topic) {
|
||||
$this->getTopic($topic)->addSubscriber($subscriber);
|
||||
}
|
||||
}
|
||||
|
||||
public function unsubscribe(SubscriberInterface $subscriber, ?array $topics=null): void
|
||||
{
|
||||
if (!$topics) {
|
||||
foreach ($this->topics as $topic) {
|
||||
$topic->removeSubscriber($subscriber);
|
||||
}
|
||||
return;
|
||||
}
|
||||
foreach ($topics as $topic) {
|
||||
$this->getTopic($topic)->removeSubscriber($subscriber);
|
||||
}
|
||||
}
|
||||
|
||||
public function getTopicCount(): int
|
||||
{
|
||||
return count($this->topics);
|
||||
@ -32,7 +58,7 @@ class TopicManager
|
||||
|
||||
public function getSubscriberCount(): int
|
||||
{
|
||||
return array_sum(array_map(fn($t) => $t->getSubscriberCount(), $this->topics));
|
||||
return count($this->subscribers);
|
||||
}
|
||||
|
||||
public function garbageCollect(): void
|
||||
|
Reference in New Issue
Block a user