I parent connection states

This commit is contained in:
Fabian @ Blax Software 2026-03-05 12:26:56 +01:00
parent 463e633713
commit 636d9eccb8
2 changed files with 78 additions and 1 deletions

View File

@ -573,8 +573,47 @@ class Handler implements MessageComponentInterface
return;
}
// Prefix-based routing: B: = broadcast, W: = whisper, else regular response
// Prefix-based routing: C: = connection data, B: = broadcast, W: = whisper, else regular response
// Avoids JSON decode overhead for regular responses (most common path)
if (str_starts_with($data, 'C:')) {
// Connection data operation from child process.
// Lets controllers set/clear/reset arbitrary properties on the
// parent's in-memory connection object via IPC.
$op = substr($data, 2);
if ($op === 'RESET') {
// Clear auth state
unset($connection->authLoaded);
$connection->user = null;
// Clear any custom connection data that was stored via C:SET
foreach (($connection->_connectionDataKeys ?? []) as $key => $_) {
unset($connection->$key);
}
$connection->_connectionDataKeys = [];
} elseif (str_starts_with($op, 'SET:')) {
// C:SET:key:json_value
$rest = substr($op, 4);
$pos = strpos($rest, ':');
if ($pos !== false) {
$key = substr($rest, 0, $pos);
$value = json_decode(substr($rest, $pos + 1));
$connection->$key = $value;
$connection->_connectionDataKeys ??= [];
$connection->_connectionDataKeys[$key] = true;
}
} elseif (str_starts_with($op, 'DEL:')) {
// C:DEL:key
$key = substr($op, 4);
unset($connection->$key);
if (isset($connection->_connectionDataKeys[$key])) {
unset($connection->_connectionDataKeys[$key]);
}
}
return;
}
if (str_starts_with($data, 'B:')) {
$bm = json_decode(substr($data, 2), true);
$this->broadcast(

View File

@ -75,6 +75,44 @@ class MockConnectionSocketPair implements ConnectionInterface
// No-op for mock
}
/**
* Reset all user-set connection state on the parent process.
*
* Clears auth state (user, authLoaded) and any custom connection data
* that was stored via setConnectionData(). Channels remain subscribed.
*
* Used after logout so the next WS message re-authenticates from Redis.
*/
public function resetConnection(): void
{
$this->ipc->sendToParent('C:RESET');
}
/**
* Store a custom key-value pair on the parent's connection object.
*
* The value is JSON-serialized over IPC and set as $connection->$key
* on the parent process. Readable by any subsequent controller via
* $this->connection->$key (proxied through __get).
*/
public function setConnectionData(string $key, mixed $value): void
{
// Update local child copy for immediate reads within this request
$this->realConnection->$key = $value;
// Signal parent to persist the change
$this->ipc->sendToParent('C:SET:' . $key . ':' . json_encode($value));
}
/**
* Remove a custom key from the parent's connection object.
*/
public function clearConnectionData(string $key): void
{
unset($this->realConnection->$key);
$this->ipc->sendToParent('C:DEL:' . $key);
}
/**
* Magic getter to proxy properties from real connection.
*/