-
Notifications
You must be signed in to change notification settings - Fork 0
SP1: Boot WebSocket worker on :8097 with shared SyncPlayManager #338
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -168,6 +168,71 @@ | |
| // REST + SSR surface. | ||
| // ----------------------------------------------------------------------------- | ||
|
|
||
| // ----------------------------------------------------------------------------- | ||
| // 4a. WebSocket worker for SyncPlay realtime communication (SP1). | ||
| // | ||
| // SyncPlay requires exactly ONE authoritative SyncPlayManager shared across all | ||
| // WS connections, so this worker runs as count=1 on port 8097 (separate from the | ||
| // HTTP workers on 8096). The manager is constructed once in onWorkerStart and | ||
| // its state persists for the lifetime of this worker process. | ||
| // | ||
| // Architecture: | ||
| // - WebSocketServer accepts an injected MessageHandler so the same handler | ||
| // instance is used for both SyncPlay message routing and general WS events. | ||
| // - SyncPlayManager::initialize() registers the per-type callbacks that route | ||
| // incoming SyncPlay messages to the appropriate handler methods. | ||
| // - ConnectionPool and MessageHandler are singletons shared within this worker. | ||
| // ----------------------------------------------------------------------------- | ||
|
|
||
| try { | ||
| $wsWorker = new Worker('websocket://0.0.0.0:8097'); | ||
| $wsWorker->count = 1; | ||
| $wsWorker->name = 'phlix-server-ws'; | ||
| $wsWorker->onWorkerStart = static function (Worker $w) use ($config, $applyCuratedCoroutineHooks): void { | ||
| $applyCuratedCoroutineHooks(); | ||
|
|
||
| // Build the container inside the fork so each worker owns its own state. | ||
| $container = ContainerFactory::create($config); | ||
|
|
||
| // Create the shared MessageHandler and ConnectionPool singletons. | ||
| $connections = \Phlix\Server\WebSocket\ConnectionPool::getInstance(); | ||
| $messageHandler = new \Phlix\Server\WebSocket\MessageHandler($connections); | ||
|
|
||
| // Construct ONE authoritative SyncPlayManager and initialize it with the | ||
| // message handler so SyncPlay message types are routed to their handlers. | ||
| /** @var \Phlix\Common\Logger\StructuredLogger $logger */ | ||
| $logger = $container->get('logger.websocket'); | ||
| $syncPlayManager = new \Phlix\Session\SyncPlay\SyncPlayManager($logger); | ||
| $syncPlayManager->initialize($messageHandler); | ||
|
|
||
| // Build and configure the WebSocket server with the shared manager. | ||
| $wsConfigRaw = $config['websocket'] ?? null; | ||
| $wsConfig = is_array($wsConfigRaw) ? $wsConfigRaw : []; | ||
| $wsConfig['host'] = $wsConfig['host'] ?? '0.0.0.0'; | ||
| $wsConfig['port'] = $wsConfig['port'] ?? 8097; | ||
| $wsConfig['stale_connection_timeout'] = $wsConfig['stale_connection_timeout'] ?? 300; | ||
| $wsConfig['stale_group_timeout'] = $wsConfig['stale_group_timeout'] ?? 3600; | ||
|
|
||
| /** @var array<string, mixed> $wsConfig */ | ||
| $wsServer = new \Phlix\Server\WebSocket\WebSocketServer($wsConfig, $messageHandler); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When the daemon is started with Useful? React with 👍 / 👎. |
||
| $wsServer->setSyncPlayManager($syncPlayManager); | ||
|
|
||
| // Trigger onStart to log the startup message and arm cleanup timers. | ||
| // The actual Workerman worker callbacks (onConnect, onMessage, onClose) | ||
| // are already bound in the WebSocketServer constructor. | ||
| $wsServer->onStart(); | ||
|
|
||
| /** @var \Phlix\Common\Logger\StructuredLogger $wsLogger */ | ||
| $wsLogger = $container->get('logger.websocket'); | ||
| $wsLogger->info('SyncPlay manager initialized', [ | ||
| 'message' => 'One SyncPlayManager instance handles all WS connections', | ||
| ]); | ||
| }; | ||
| } catch (\Throwable $e) { | ||
| // The WS worker is best-effort; never block the HTTP server. | ||
| trigger_error('Failed to set up WebSocket worker: ' . $e->getMessage(), E_USER_WARNING); | ||
| } | ||
|
|
||
| // ----------------------------------------------------------------------------- | ||
| // 4b. Managed worker processes (1.1b). | ||
| // | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new
config/server.phpblock exposeswebsocket.hostandwebsocket.port, but the actual Workerman listener is still hard-coded to0.0.0.0:8097. In any deployment that overrides the config, the code below may log/construct the inner server with the configured values while the socket that clients actually reach still binds to all interfaces on 8097, so the configured WebSocket endpoint is ignored. Build this listen URI from$config['websocket']before creating$wsWorker.Useful? React with 👍 / 👎.