Skip to content
This repository was archived by the owner on Feb 7, 2024. It is now read-only.

[3.0] Initial commit for Amphp Websockets. #756

Closed
wants to merge 2 commits into from
Closed

[3.0] Initial commit for Amphp Websockets. #756

wants to merge 2 commits into from

Conversation

DarkGhostHunter
Copy link
Contributor

I know you're making a 2.0 and it has been having dozens of betas. Before you flip your tables, just hear me out: this is a rewrite of Laravel Websockets using Amphp.

  • It uses Amphp Websocket implementation.
    • The "Loop" driver is detected automatically by Amphp, no water needed.
    • The "Loop" is static.
  • It uses Amphp Redis implementation, 99% compatible with latest Redis version.
  • It's ready to be compatible with Pusher 6.x if this PR succeeds.
  • Removed support for Laravel 7.x and below (they're dead).
  • Removed support for PHP 7.2 and below (see last point).

You can test this by simply using websockets:serve, connecting directly, and issuing an "Hello World".

There was some major refactoring in the most important areas, but there is still work to do to make separate the WebSocket implementation for the developer, from the actual Server doing the heavy lifting. Talking about pending things,

Todo:

  • General: Clear the schematic of the Package: Addresses -> Server(Socket, signal, process, etc) -> Handler -> Router -> Middleware -> Controllers
  • General: Move all Handlers to their own directory with their own Routes and controllers.
  • Dependencies: Check and try to reuse Laravel Requests/Responses.
  • Store: Create a JsonStore statistics for development, fresh at each Server Start.
  • Contracts: Create a WebsocketClient contract to allow swapping between Amphp, React, or Octane.
  • Contracts: Create a WebsocketServer contract to allow swapping between Amphp, React, or Octane.
  • Contracts: Create a AsyncRedisClient contract to allow swapping between Amphp, React, or Octane.
  • Contracts: Create a LoopInterface contract to allow swapping between Amphp, React or Octane.
  • Contracts: Create a MessageInterface contract to allow swapping between Amphp, React or Octane.
  • Low Priority: Come with a simpler Router design.
  • Low Priority: Add PHPDoc to Facades.
  • Low Priority: Don't use Facades on internal source code, unless exposed.
  • General: Fix async calls parameters when using Promise::onResolve().
  • Channels: Fix Channels and ChannelManagers to use new code.
  • General: Enforce appId as the application name in snake_case.
  • PITA: Allow connections to migrate from one to other server.
  • General: Refactor to use Dependency Injection where applicable.

I think this package may have a good chance to be THE Websocket package that can work on major concurrency frameworks (Amphp, React, soon Octane) without having marry just one dependency.

PD: For Octane, Websockets must be enabled on RR 2.0, and we're still waiting.

@mpociot mpociot mentioned this pull request May 3, 2021
4 tasks
@mpociot
Copy link
Member

mpociot commented May 3, 2021

Hi @DarkGhostHunter

First of all, thank you very much for taking the time to write this PR.

I will find some time to discuss with @rennokki how he wants to handle the current 2.x version and release. I actually have scheduled time to work on the outstanding MySQL app manager this week and I feel like this is one of the last bigger pieces of a 2.0 release.

I also sent you a private Twitter DM, hoping that we can find some time for a Telegram chat/Google Hangouts, to discuss this PR and everything involved in it (hopefully together with @rennokki, if he wants to).

With Laravel Octane, Swoole, and RoadRunner, I agree that we should think about how this package can be used for this as well.

Right now, I simply don't know when and how we should approach this, as a lot of time and work already went into the 2.0 version from @rennokki and a lot of other contributors.

@DarkGhostHunter
Copy link
Contributor Author

DarkGhostHunter commented May 3, 2021

Hi @DarkGhostHunter

First of all, thank you very much for taking the time to write this PR.

I will find some time to discuss with @rennokki how he wants to handle the current 2.x version and release. I actually have scheduled time to work on the outstanding MySQL app manager this week and I feel like this is one of the last bigger pieces of a 2.0 release.

I also sent you a private Twitter DM, hoping that we can find some time for a Telegram chat/Google Hangouts, to discuss this PR and everything involved in it (hopefully together with @rennokki, if he wants to).

With Laravel Octane, Swoole, and RoadRunner, I agree that we should think about how this package can be used for this as well.

Right now, I simply don't know when and how we should approach this, as a lot of time and work already went into the 2.0 version from @rennokki and a lot of other contributors.

I know, that's why I didn't went the extra mile. I just thought something was wrong after so many betas and a lot of dependencies going around. Using Amphp lead me to a successful result with less dependencies.

In my opinion, 2.0 should run its course, and keep 3.0 developing in parallel, while adding features from 2.0 into 3.0 when possible. The next version should be done just before Octane is stable, as it should be the last thing to add as a driver.

@DarkGhostHunter
Copy link
Contributor Author

After checking Ratchet, I saw it uses ReactPHP behind the scenes.

There is no guarantee that Ratchet someday will change async library to anything else, but since ReactPHP only offers the basic foundation, I will take Ratchet and ReactPHP as the same driver: 'react'.

@DarkGhostHunter
Copy link
Contributor Author

DarkGhostHunter commented May 5, 2021

TL;DR: Interoperability is impossible as API are enforced once inside each implementation's async context. Amphp offers less entangled dependencies, but requires to use yield almost everywhere.


After fighting a whole day with ReactPHP, Amphp, Swoole, and async and abstractions, I humbly declare that interoperability between ReactPHP, Amphp, and Swoole (in someway) is close to impossible.

In other words, each async library offers their own API, and once inside a async context you're bound to not break that API. As you can guess, once inside the Websocket Server, every piece of code must abide to that API.

For example, in Amphp, almost everything that needs to be resolved is called with yield.

public function userController(MessageContract $message)
{
    $contents = yield $message;

    $contents .= ' and end.';

    yield $contents
}

Thus, using yield transforms everything into a generator. Swapping Amphp for anything else would break userland code. And using the wait helper inside an async context stops all the context, which is the Websocket Server itself.

While the Amphp implementation of the WebSocket Server is a little more barebones, it ensures the whole server context uses yield making it highly non-blocking, but as you can guess the API roots of async are too much deep between each offering.

Considering the huge gains of using Swoole (and soon Roadrunner) for WebSockets, I'll wait until these both are stable to move this codebase to a more cleaner and interoperable syntax, as ReactPHP, Amphp, and Swoole/Roadrunner don't mix very well together.

@DarkGhostHunter DarkGhostHunter deleted the feat/amphp branch May 6, 2021 01:27
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants