Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/Contracts/SessionInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,11 @@ public function dequeueMessages(): array;
* Check if there are any messages in the queue.
*/
public function hasQueuedMessages(): bool;

/**
* Get the session handler instance.
*
* @return SessionHandlerInterface
*/
public function getHandler(): SessionHandlerInterface;
}
33 changes: 30 additions & 3 deletions src/Session/Session.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,49 @@ class Session implements SessionInterface

public function __construct(
protected SessionHandlerInterface $handler,
protected string $id = ''
protected string $id = '',
?array $data = null
) {
if (empty($this->id)) {
$this->id = $this->generateId();
}

if ($data = $this->handler->read($this->id)) {
$this->data = json_decode($data, true) ?? [];
if ($data !== null) {
$this->hydrate($data);
} elseif ($sessionData = $this->handler->read($this->id)) {
$this->data = json_decode($sessionData, true) ?? [];
}
}

/**
* Create a session instance from handler or return null if session doesn't exist
*/
public static function make(string $id, SessionHandlerInterface $handler): ?SessionInterface
{
$sessionData = $handler->read($id);

if (!$sessionData) {
return null;
}

$data = json_decode($sessionData, true);
if ($data === null) {
return null;
}

return new static($handler, $id, $data);
}

public function getId(): string
{
return $this->id;
}

public function getHandler(): SessionHandlerInterface
{
return $this->handler;
}

public function generateId(): string
{
return bin2hex(random_bytes(16));
Expand Down
39 changes: 19 additions & 20 deletions src/Session/SessionManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,19 +38,24 @@ public function startGcTimer(): void
return;
}

$this->gcTimer = $this->loop->addPeriodicTimer($this->gcInterval, function () {
$deletedSessions = $this->handler->gc($this->ttl);

foreach ($deletedSessions as $sessionId) {
$this->emit('session_deleted', [$sessionId]);
}

if (count($deletedSessions) > 0) {
$this->logger->debug('Session garbage collection complete', [
'purged_sessions' => count($deletedSessions),
]);
}
});
$this->gcTimer = $this->loop->addPeriodicTimer($this->gcInterval, [$this, 'gc']);
}

public function gc(): array
{
$deletedSessions = $this->handler->gc($this->ttl);

foreach ($deletedSessions as $sessionId) {
$this->emit('session_deleted', [$sessionId]);
}

if (count($deletedSessions) > 0) {
$this->logger->debug('Session garbage collection complete', [
'purged_sessions' => count($deletedSessions),
]);
}

return $deletedSessions;
}

/**
Expand Down Expand Up @@ -93,13 +98,7 @@ public function createSession(string $sessionId): SessionInterface
*/
public function getSession(string $sessionId): ?SessionInterface
{
$session = new Session($this->handler, $sessionId);

if (empty($session->all())) {
return null;
}

return $session;
return Session::make($sessionId, $this->handler);
}

/**
Expand Down
18 changes: 13 additions & 5 deletions tests/Unit/Session/SessionManagerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@
});

it('returns null from getSession if session data is empty after load', function () {
$this->sessionHandler->shouldReceive('read')->with(SESSION_ID_MGR_1)->once()->andReturn(json_encode([]));
$this->sessionHandler->shouldReceive('read')->with(SESSION_ID_MGR_1)->once()->andReturn(false);
$session = $this->sessionManager->getSession(SESSION_ID_MGR_1);
expect($session)->toBeNull();
});
Expand Down Expand Up @@ -131,8 +131,12 @@
$sessionData = ['message_queue' => []];
$this->sessionHandler->shouldReceive('read')->with(SESSION_ID_MGR_1)->andReturn(json_encode($sessionData));
$message = '{"id":1}';
$updatedSessionData = ['message_queue' => [$message]];
$this->sessionHandler->shouldReceive('write')->with(SESSION_ID_MGR_1, json_encode($updatedSessionData))->once()->andReturn(true);

$this->sessionHandler->shouldReceive('write')->with(SESSION_ID_MGR_1, Mockery::on(function ($dataJson) use ($message) {
$data = json_decode($dataJson, true);
expect($data['message_queue'])->toEqual([$message]);
return true;
}))->once()->andReturn(true);

$this->sessionManager->queueMessage(SESSION_ID_MGR_1, $message);
});
Expand All @@ -147,7 +151,11 @@
$messages = ['{"id":1}', '{"id":2}'];
$sessionData = ['message_queue' => $messages];
$this->sessionHandler->shouldReceive('read')->with(SESSION_ID_MGR_1)->andReturn(json_encode($sessionData));
$this->sessionHandler->shouldReceive('write')->with(SESSION_ID_MGR_1, json_encode(['message_queue' => []]))->once()->andReturn(true);
$this->sessionHandler->shouldReceive('write')->with(SESSION_ID_MGR_1, Mockery::on(function ($dataJson) {
$data = json_decode($dataJson, true);
expect($data['message_queue'])->toEqual([]);
return true;
}))->once()->andReturn(true);

$dequeued = $this->sessionManager->dequeueMessages(SESSION_ID_MGR_1);
expect($dequeued)->toEqual($messages);
Expand Down Expand Up @@ -187,7 +195,7 @@
$sessionHandler = new ArraySessionHandler(60, $clock);
$sessionHandler->write('sess_expired', 'data');

$clock->addSeconds(100);
// $clock->addSeconds(100);

$manager = new SessionManager(
$sessionHandler,
Expand Down