Skip to content

Commit

Permalink
Adds cache managers for use with API Gateway (#26)
Browse files Browse the repository at this point in the history
* implement cache manager

* implement contract

* Fix code styling

* wip

* wip
  • Loading branch information
joedixon authored Dec 4, 2023
1 parent 0858633 commit 1c75d78
Show file tree
Hide file tree
Showing 24 changed files with 792 additions and 291 deletions.
2 changes: 1 addition & 1 deletion phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<env name="PUSHER_APP_ID" value="123456"/>
<env name="PUSHER_APP_KEY" value="pusher-key"/>
<env name="PUSHER_APP_SECRET" value="pusher-secret"/>
<env name="REVERB_API_GATEWAY_CONNECTION_CACHE" value="redis"/>
<env name="REVERB_API_GATEWAY_CONNECTION_CACHE" value="file"/>
</php>
<source>
<include>
Expand Down
5 changes: 4 additions & 1 deletion src/Channels/Channel.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@

namespace Laravel\Reverb\Channels;

use Laravel\Reverb\Concerns\SerializesChannels;
use Laravel\Reverb\Contracts\ChannelConnectionManager;
use Laravel\Reverb\Contracts\Connection;

class Channel
{
use SerializesChannels;

/**
* The channel connections.
*
Expand All @@ -16,7 +19,7 @@ class Channel

public function __construct(protected string $name)
{
$this->connections = app(ChannelConnectionManager::class);
$this->connections = app(ChannelConnectionManager::class)->for($this->name);
}

/**
Expand Down
27 changes: 27 additions & 0 deletions src/Concerns/SerializesChannels.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

namespace Laravel\Reverb\Concerns;

use Laravel\Reverb\Contracts\ChannelConnectionManager;

trait SerializesChannels
{
/**
* Prepare the connection instance values for serialization.
*/
public function __serialize(): array
{
return [
'name' => $this->name,
];
}

/**
* Restore the connection after serialization.
*/
public function __unserialize(array $values): void
{
$this->name = $values['name'];
$this->connections = app(ChannelConnectionManager::class)->for($this->name);
}
}
5 changes: 5 additions & 0 deletions src/Contracts/ChannelConnectionManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@

interface ChannelConnectionManager
{
/**
* The channel name.
*/
public function for(string $name): ChannelConnectionManager;

/**
* Add a connection.
*/
Expand Down
22 changes: 0 additions & 22 deletions src/Contracts/Connection.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ abstract class Connection
*/
protected $hasBeenPinged = false;

protected $pusher;

public function __construct(
protected Application $application,
protected ?string $origin
Expand Down Expand Up @@ -128,24 +126,4 @@ public function isStale(): bool
{
return $this->isInactive() && $this->hasBeenPinged;
}

/**
* Hydrate a serialized connection.
*/
public static function hydrate(Connection|string $connection): Connection
{
return is_object($connection)
? $connection
: unserialize($connection);
}

/**
* Hydrate a serialized connection.
*/
public static function dehydrate(Connection $connection): Connection|string
{
return $connection instanceof SerializableConnection
? serialize($connection)
: $connection;
}
}
36 changes: 36 additions & 0 deletions src/Contracts/ConnectionManager.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

namespace Laravel\Reverb\Contracts;

interface ConnectionManager
{
/**
* Add a new connection.
*/
public function connect(Connection $connection): void;

/**
* Find a connection.
*/
public function find(string $id): ?Connection;

/**
* Get all the connections.
*/
public function all(): array;

/**
* Update the state of a connection.
*/
public function update(Connection $connection): void;

/**
* Forget a connection.
*/
public function forget(Connection $connection): void;

/**
* Flush all connections.
*/
public function flush(): void;
}
12 changes: 12 additions & 0 deletions src/Managers/ArrayChannelConnectionManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,25 @@

class ArrayChannelConnectionManager implements ChannelConnectionManager
{
protected string $name;

/**
* Connection store.
*
* @var array<string, \Laravel\Reverb\Servers\Reverb\ChannelConnection>
*/
protected $connections = [];

/**
* The channel name.
*/
public function for(string $name): ChannelConnectionManager
{
$this->name = $name;

return $this;
}

/**
* Add a connection.
*/
Expand Down
111 changes: 111 additions & 0 deletions src/Managers/CacheChannelConnectionManager.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
<?php

namespace Laravel\Reverb\Managers;

use Illuminate\Contracts\Cache\Repository;
use Laravel\Reverb\Contracts\ChannelConnectionManager;
use Laravel\Reverb\Contracts\Connection;
use Laravel\Reverb\Contracts\ConnectionManager;
use Laravel\Reverb\Servers\Reverb\ChannelConnection;

class CacheChannelConnectionManager implements ChannelConnectionManager
{
protected string $name;

public function __construct(
protected Repository $repository,
protected ConnectionManager $connections,
protected $prefix = 'reverb'
) {
//
}

/**
* The channel name.
*/
public function for(string $name): ChannelConnectionManager
{
$this->name = $name;

return $this;
}

/**
* Get the key for the channels.
*/
protected function key(): string
{
return "{$this->prefix}:{$this->name}";
}

/**
* Add a connection.
*/
public function add(Connection $connection, array $data): void
{
$connections = $this->repository->get($this->key(), []);

$connections[$connection->identifier()] = $data;

$this->repository->put($this->key(), $connections);
}

/**
* Remove a connection.
*/
public function remove(Connection $connection): void
{
$connections = $this->repository->get($this->key());

unset($connections[$connection->identifier()]);

$this->repository->put($this->key(), $connections);
}

/**
* Find a connection in the set.
*/
public function find(Connection $connection): ?ChannelConnection
{
return $this->findById($connection->identifier());
}

/**
* Find a connection in the set by its ID.
*/
public function findById(string $id): ?ChannelConnection
{
$connection = $this->connections->find($id);

if (! $connection) {
return null;
}

return new ChannelConnection(
$connection,
$this->repository->get($this->key())[$id] ?? []
);
}

/**
* Get all the connections.
*/
public function all(): array
{
$connections = $this->connections->all();
$channelConnections = $this->repository->get($this->key(), []);
$allConnections = array_intersect_key($connections, $channelConnections);

return array_map(function ($connection) use ($channelConnections) {
return new ChannelConnection($connection, $channelConnections[$connection->identifier()]);
}, $allConnections);
}

/**
* Flush the channel connection manager.
*/
public function flush(): void
{
$this->repository->put($this->key(), []);
}
}
Loading

0 comments on commit 1c75d78

Please sign in to comment.