-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
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
Long-running tasks blocking the WebSocket process #1058
Comments
Try to use You can find more information here: #937 |
🙏 Thank you @joanhey for the help. The <?php
namespace ChessServer\Command\Game;
use Chess\SanHeuristic;
use Chess\Function\CompleteFunction;
use Chess\Variant\Chess960\Board as Chess960Board;
use Chess\Variant\Chess960\FEN\StrToBoard as Chess960FenStrToBoard;
use Chess\Variant\Classical\Board as ClassicalBoard;
use Chess\Variant\Classical\FEN\StrToBoard as ClassicalFenStrToBoard;
use ChessServer\Command\AbstractCommand;
use ChessServer\Socket\AbstractSocket;
class HeuristicCommand extends AbstractCommand
{
public function __construct()
{
$this->name = '/heuristic';
$this->description = 'Balance of a chess heuristic.';
$this->params = [
'params' => '<string>',
];
}
public function validate(array $argv)
{
return count($argv) - 1 === count($this->params);
}
public function run(AbstractSocket $socket, array $argv, int $id)
{
$params = json_decode(stripslashes($argv[1]), true);
if ($params['variant'] === Chess960Board::VARIANT) {
$startPos = str_split($params['startPos']);
$board = isset($params['fen'])
? (new Chess960FenStrToBoard($params['fen'], $startPos))->create()
: new Chess960Board($startPos);
} elseif ($params['variant'] === ClassicalBoard::VARIANT) {
$board = isset($params['fen'])
? (new ClassicalFenStrToBoard($params['fen']))->create()
: new ClassicalBoard();
}
$balance = (new SanHeuristic(
new CompleteFunction(),
$params['name'],
$params['movetext'],
$board
))->getBalance();
return $socket->getClientStorage()->send([$id], [
$this->name => $balance,
]);
}
} And this is how I'm trying to defer it without much success. <?php
namespace ChessServer\Command\Game;
use Chess\SanHeuristic;
use Chess\Function\CompleteFunction;
use Chess\Variant\Chess960\Board as Chess960Board;
use Chess\Variant\Chess960\FEN\StrToBoard as Chess960FenStrToBoard;
use Chess\Variant\Classical\Board as ClassicalBoard;
use Chess\Variant\Classical\FEN\StrToBoard as ClassicalFenStrToBoard;
use ChessServer\Command\AbstractCommand;
use ChessServer\Socket\AbstractSocket;
use Workerman\Timer;
class HeuristicCommand extends AbstractCommand
{
public function __construct()
{
$this->name = '/heuristic';
$this->description = 'Balance of a chess heuristic.';
$this->params = [
'params' => '<string>',
];
}
public function validate(array $argv)
{
return count($argv) - 1 === count($this->params);
}
public function run(AbstractSocket $socket, array $argv, int $id)
{
$params = json_decode(stripslashes($argv[1]), true);
if ($params['variant'] === Chess960Board::VARIANT) {
$startPos = str_split($params['startPos']);
$board = isset($params['fen'])
? (new Chess960FenStrToBoard($params['fen'], $startPos))->create()
: new Chess960Board($startPos);
} elseif ($params['variant'] === ClassicalBoard::VARIANT) {
$board = isset($params['fen'])
? (new ClassicalFenStrToBoard($params['fen']))->create()
: new ClassicalBoard();
}
Timer::add(0.001, function() use ($params, $board, $socket, $id) {
$balance = (new SanHeuristic(
new CompleteFunction(),
$params['name'],
$params['movetext'],
$board
))->getBalance();
return $socket->getClientStorage()->send([$id], [
$this->name => $balance,
]);
}, persistent: false);
}
} Is this correct or am I wrong in doing so? // ...
Timer::add(0.001, function() use ($params, $board, $socket, $id) {
$balance = (new SanHeuristic(
new CompleteFunction(),
$params['name'],
$params['movetext'],
$board
))->getBalance();
return $socket->getClientStorage()->send([$id], [
$this->name => $balance,
]);
}, persistent: false);
// ... Happy coding. |
PHP Chess Server is a flexible asynchronous PHP chess server allowing support for multiple async PHP frameworks. At the moment is using Workerman and Ratchet with the default one being Workerman. Also we'd want to support AMPHP. This is made possible thanks to a polymorphic, object-oriented WebSocket implementation that is providing chess functionality. We're thinking along the lines of solving the concurrency issue using PCNTL functions with the help of spatie/async agnostically to the async PHP frameworks. |
Until recently, we had implemented our chess functionality on two different servers: The WebSocket server and the web server. The former was intended to run real-time tasks while the latter hosted a REST-like API for long-running tasks like database queries, ad hoc reportings, and so on, which would take a few seconds to run.
This separation of concerns was perfeclty fine.
However, at some point it was decided to get rid of the web server and try out an implementation completely based on WebSockets. All functionality, which is to say real-time operations and long-running operations, was moved to the WebSocket server. The reason being was mainly because this setup looked simpler and cheaper.
The thing is, whether using Workerman or Ratchet, the staging server has demonstrated that there is something wrong with this setup.
If two users are playing chess online (real-time) while another user is generating an ad hoc report (long-running) the two users playing online will experience a bottleneck because the report generation seems to be blocking the WebScocket process for a few seconds.
The current WebSocket server is pretty much unusable if there are a few users connected at the same time:
Are we missing something?
Could you please provide some guidance on how to implement long-running tasks with WebSockets? Or should we get back to the previous API implementation for the long-running tasks?
🙏 Thank you for the help, it is very much appreciated!
The text was updated successfully, but these errors were encountered: