diff --git a/src/Server/Manager.php b/src/Server/Manager.php index d90a4347..0f751cf6 100644 --- a/src/Server/Manager.php +++ b/src/Server/Manager.php @@ -114,7 +114,10 @@ protected function initialize() { $this->createTables(); $this->prepareWebsocket(); - $this->setSwooleServerListeners(); + + if (! $this->container->make(Server::class)->taskworker) { + $this->setSwooleServerListeners(); + } } /** @@ -122,13 +125,14 @@ protected function initialize() */ protected function setSwooleServerListeners() { + $server = $this->container->make(Server::class); foreach ($this->events as $event) { $listener = Str::camel("on_$event"); $callback = method_exists($this, $listener) ? [$this, $listener] : function () use ($event) { $this->container->make('events')->dispatch("swoole.$event", func_get_args()); }; - $this->container->make(Server::class)->on($event, $callback); + $server->on($event, $callback); } } @@ -170,13 +174,7 @@ public function onWorkerStart($server) $this->container->make('events')->dispatch('swoole.workerStart', func_get_args()); - // don't init laravel app in task workers - if ($server->taskworker) { - $this->setProcessName('task process'); - - return; - } - $this->setProcessName('worker process'); + $this->setProcessName($server->taskworker ? 'task process' : 'worker process'); // clear events instance in case of repeated listeners in worker process Facade::clearResolvedInstance('events'); diff --git a/src/Websocket/Facades/Room.php b/src/Websocket/Facades/Room.php index 5b1919c2..5050e4f6 100644 --- a/src/Websocket/Facades/Room.php +++ b/src/Websocket/Facades/Room.php @@ -5,9 +5,9 @@ use Illuminate\Support\Facades\Facade; /** - * @method static this prepare() - * @method static this add($fd, $rooms) - * @method static this delete($fd, $rooms) + * @method static $this prepare() + * @method static $this add($fd, $rooms) + * @method static $this delete($fd, $rooms) * @method static array getClients($room) * @method static array getRooms($fd) * @@ -24,4 +24,4 @@ protected static function getFacadeAccessor() { return 'swoole.room'; } -} \ No newline at end of file +} diff --git a/src/Websocket/Facades/Websocket.php b/src/Websocket/Facades/Websocket.php index 9f054036..6fedbcb4 100644 --- a/src/Websocket/Facades/Websocket.php +++ b/src/Websocket/Facades/Websocket.php @@ -5,30 +5,30 @@ use Illuminate\Support\Facades\Facade; /** - * @method static this broadcast() - * @method static this to($values) - * @method static this join($rooms) - * @method static this leave($rooms) + * @method static $this broadcast() + * @method static $this to($values) + * @method static $this join($rooms) + * @method static $this leave($rooms) * @method static boolean emit($event, $data) - * @method static this in($room) - * @method static this on($event, $callback) + * @method static $this in($room) + * @method static $this on($event, $callback) * @method static boolean eventExists($event) * @method static mixed call($event, $data) * @method static boolean close($fd) - * @method static this setSender($fd) + * @method static $this setSender($fd) * @method static int getSender() * @method static boolean getIsBroadcast() * @method static array getTo() - * @method static this reset() - * @method static this middleware($middleware) - * @method static this setContainer($container) - * @method static this setPipeline($pipeline) + * @method static $this reset() + * @method static $this middleware($middleware) + * @method static $this setContainer($container) + * @method static $this setPipeline($pipeline) * @method static \Illuminate\Contracts\Pipeline\Pipeline getPipeline() * @method static mixed loginUsing($user) - * @method static this loginUsingId($userId) - * @method static this logout() - * @method static this toUser($users) - * @method static this toUserId($userIds) + * @method static $this loginUsingId($userId) + * @method static $this logout() + * @method static $this toUser($users) + * @method static $this toUserId($userIds) * @method static string getUserId() * @method static boolean isUserIdOnline($userId) * @@ -45,4 +45,4 @@ protected static function getFacadeAccessor() { return 'swoole.websocket'; } -} \ No newline at end of file +} diff --git a/src/Websocket/Middleware/Authenticate.php b/src/Websocket/Middleware/Authenticate.php index ccc4bfa9..caf1c675 100644 --- a/src/Websocket/Middleware/Authenticate.php +++ b/src/Websocket/Middleware/Authenticate.php @@ -42,6 +42,7 @@ public function __construct(Auth $auth) public function handle($request, Closure $next) { try { + $this->auth->setRequest($request); if ($user = $this->auth->authenticate()) { $request->setUserResolver(function () use ($user) { return $user; diff --git a/src/Websocket/Rooms/RedisRoom.php b/src/Websocket/Rooms/RedisRoom.php index 2a5ba9e9..365b0b25 100644 --- a/src/Websocket/Rooms/RedisRoom.php +++ b/src/Websocket/Rooms/RedisRoom.php @@ -219,7 +219,10 @@ public function getValue(string $key, string $table) { $this->checkTable($table); - return $this->redis->smembers($this->getKey($key, $table)); + $result = $this->redis->smembers($this->getKey($key, $table)); + + // Try to fix occasional non-array returned result + return is_array($result) ? $result : []; } /** diff --git a/src/Websocket/Websocket.php b/src/Websocket/Websocket.php index 18fe56bd..aa9c45bb 100644 --- a/src/Websocket/Websocket.php +++ b/src/Websocket/Websocket.php @@ -8,6 +8,7 @@ use Illuminate\Support\Facades\Config; use InvalidArgumentException; use SwooleTW\Http\Server\Facades\Server; +use SwooleTW\Http\Server\Manager; use SwooleTW\Http\Websocket\Rooms\RoomContract; /** @@ -172,17 +173,25 @@ public function emit(string $event, $data): bool return false; } - $result = App::make(Server::class)->task([ - 'action' => static::PUSH_ACTION, - 'data' => [ - 'sender' => $this->sender, - 'fds' => $fds, - 'broadcast' => $this->isBroadcast, - 'assigned' => $assigned, - 'event' => $event, - 'message' => $data, - ], - ]); + $payload = [ + 'sender' => $this->sender, + 'fds' => $fds, + 'broadcast' => $this->isBroadcast, + 'assigned' => $assigned, + 'event' => $event, + 'message' => $data, + ]; + + $result = true; + $server = App::make(Server::class); + if ($server->taskworker) { + App::make(Manager::class)->pushMessage($server, $payload); + } else { + $result = $server->task([ + 'action' => static::PUSH_ACTION, + 'data' => $payload + ]); + } $this->reset(); diff --git a/tests/Server/ManagerTest.php b/tests/Server/ManagerTest.php index 31f8db91..2f56f526 100644 --- a/tests/Server/ManagerTest.php +++ b/tests/Server/ManagerTest.php @@ -178,7 +178,8 @@ public function testOnTaskWorkerStart() return $this->getEvent('swoole.workerStart'); }); - $manager = $this->getManager($container); + $path = __DIR__ . '/../fixtures'; + $manager = $this->getManager($container, $framework = 'laravel', $path); $this->assertNull($manager->onWorkerStart($server)); } diff --git a/tests/Websocket/Middleware/AuthenticateTest.php b/tests/Websocket/Middleware/AuthenticateTest.php index fcd5b4f9..d7dfa5be 100644 --- a/tests/Websocket/Middleware/AuthenticateTest.php +++ b/tests/Websocket/Middleware/AuthenticateTest.php @@ -12,14 +12,17 @@ class AuthenticateTest extends TestCase { public function testAuthenticate() { + $request = m::mock(Request::class); + $request->shouldReceive('setUserResolver') + ->once(); + $auth = m::mock(Auth::class); $auth->shouldReceive('authenticate') ->once() ->andReturn('user'); - - $request = m::mock(Request::class); - $request->shouldReceive('setUserResolver') - ->once(); + $auth->shouldReceive('setRequest') + ->with($request) + ->once(); $middleware = new Authenticate($auth); $middleware->handle($request, function ($next) { diff --git a/tests/Websocket/WebsocketTest.php b/tests/Websocket/WebsocketTest.php index 967ac49d..9f1c5631 100644 --- a/tests/Websocket/WebsocketTest.php +++ b/tests/Websocket/WebsocketTest.php @@ -2,18 +2,19 @@ namespace SwooleTW\Http\Tests\Websocket; -use Illuminate\Container\Container; -use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; +use Mockery as m; use Illuminate\Http\Request; +use InvalidArgumentException; use Illuminate\Pipeline\Pipeline; +use SwooleTW\Http\Server\Manager; +use SwooleTW\Http\Tests\TestCase; +use Illuminate\Container\Container; use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\Config; -use InvalidArgumentException; -use Mockery as m; +use SwooleTW\Http\Websocket\Websocket; use SwooleTW\Http\Server\Facades\Server; -use SwooleTW\Http\Tests\TestCase; use SwooleTW\Http\Websocket\Rooms\RoomContract; -use SwooleTW\Http\Websocket\Websocket; +use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; class WebsocketTest extends TestCase { @@ -326,12 +327,15 @@ public function testEmit() ->times(3) ->andReturn([3, 4, 5]); + $server = m::mock('server'); + $server->taskworker = false; + App::shouldReceive('make') ->with(Server::class) ->once() - ->andReturnSelf(); + ->andReturn($server); - App::shouldReceive('task') + $server->shouldReceive('task') ->with([ 'action' => 'push', 'data' => [ @@ -355,6 +359,54 @@ public function testEmit() $this->assertFalse($websocket->getIsBroadcast()); } + public function testEmitInTaskWorker() + { + $sender = 1; + $to = [1, 2, 'a', 'b', 'c']; + $broadcast = true; + $room = m::mock(RoomContract::class); + $room->shouldReceive('getClients') + ->with(m::type('string')) + ->times(3) + ->andReturn([3, 4, 5]); + + $payload = [ + 'sender' => $sender, + 'fds' => [1, 2, 3, 4, 5], + 'broadcast' => $broadcast, + 'assigned' => true, + 'event' => $event = 'event', + 'message' => $data = 'data', + ]; + + $server = m::mock('server'); + $server->taskworker = true; + + $manager = m::mock(Manager::class); + $manager->shouldReceive('pushMessage') + ->with($server, $payload) + ->once(); + + App::shouldReceive('make') + ->with(Server::class) + ->once() + ->andReturn($server); + + App::shouldReceive('make') + ->with(Manager::class) + ->once() + ->andReturn($manager); + + $websocket = $this->getWebsocket($room); + $websocket->setSender($sender) + ->to($to) + ->broadcast() + ->emit($event, $data); + + $this->assertSame([], $websocket->getTo()); + $this->assertFalse($websocket->getIsBroadcast()); + } + public function testClose() { $fd = 1;