From 7ee4d2366df1f0d58212d3388aefcfcb3619f803 Mon Sep 17 00:00:00 2001 From: cclilshy Date: Fri, 1 Nov 2024 16:47:57 +0800 Subject: [PATCH 1/2] [PHP/ripple] Added ripple coroutine engine. --- frameworks/PHP/ripple/README.md | 75 ++++++++ frameworks/PHP/ripple/benchmark_config.json | 29 +++ frameworks/PHP/ripple/composer.json | 10 + frameworks/PHP/ripple/fortunes.php | 18 ++ frameworks/PHP/ripple/ripple.dockerfile | 32 ++++ frameworks/PHP/ripple/server.php | 200 ++++++++++++++++++++ 6 files changed, 364 insertions(+) create mode 100644 frameworks/PHP/ripple/README.md create mode 100644 frameworks/PHP/ripple/benchmark_config.json create mode 100644 frameworks/PHP/ripple/composer.json create mode 100644 frameworks/PHP/ripple/fortunes.php create mode 100644 frameworks/PHP/ripple/ripple.dockerfile create mode 100644 frameworks/PHP/ripple/server.php diff --git a/frameworks/PHP/ripple/README.md b/frameworks/PHP/ripple/README.md new file mode 100644 index 00000000000..ce4d89d0bc2 --- /dev/null +++ b/frameworks/PHP/ripple/README.md @@ -0,0 +1,75 @@ +

+Logo +

+

+Build Status +Download statistics +Stable version +License +

+

+Ripple is a modern, high-performance native PHP coroutine engine designed to solve PHP's challenges in high concurrency, complex network communication and data operations. +The engine uses an innovative architecture and efficient programming model to provide powerful and flexible backend support for modern web and web applications. +By using ripple, you will experience the advantages of managing tasks from a global view of the system and efficiently handling network traffic and data.

+ +## Install + +````bash +composer require cloudtay/ripple +```` + +## Latest documentation + +You can visit `ripple`’s [documentation](https://ripple.cloudtay.com/) to start reading + +We recommend that you start with [Manual Installation](https://ripple.cloudtay.com/docs/install/professional) to better +understand the workflow of ripple + +If you want to quickly deploy and use `ripple` services, you can directly +visit [Quick Deployment](https://ripple.cloudtay.com/docs/install/server) + +## Appendix + +### Applicable component library + +> We allow users to choose applicable component libraries by themselves. All components can be used as described in the +> document without additional configuration. + +**🚀 [Guzzle](https://docs.guzzlephp.org/en/stable/)** +PHP is the most widely used HTTP client + +**🔥 [AmPHP](https://amphp.org/)** +Provides rich PHP asynchronous components for users to encapsulate by themselves + +**🚀 [Driver](https://github.com/cloudtay/ripple-driver)** +The official high-performance driver library provides seamless access to your traditional applications. + +**🚀 [Webman-coroutine](https://github.com/workbunny/webman-coroutine)** +The workbunny team's integrated webman coroutine extension provides coroutine support for Webman. + +**🟢[ripple](https://github.com/cloudtay/ripple)** +Provides standard coroutine architecture and tools for rapid development or packaging of traditional applications + +### Event Library Guide + +| Extension Types | Recommended Use | Compatibility | Description | +|:---------------:|:---------------:|:-------------:|:--------------------------------------------------------------------------------------------------------------------:| +| `libev` | 🏅️ | 🟢️ | `Ev` is a more efficient event extension that performs consistently in various systems and is recommended to be used | +| `Native` | ️ | 🟢 | Support the use of PHP's built-in select mechanism | +| `event` | | 🌗 | The event characteristics under different systems are not uniform, and their use is not recommended | + +## Special thanks + + + jetbrains + + +[Jetbrains](https://www.jetbrains.com/?from=ripple) provides free development tools for this project + +### Contact information + +`Email` jingnigg@gmail.com + +`WeChat` jingnigg + +--- diff --git a/frameworks/PHP/ripple/benchmark_config.json b/frameworks/PHP/ripple/benchmark_config.json new file mode 100644 index 00000000000..4c625c29bbe --- /dev/null +++ b/frameworks/PHP/ripple/benchmark_config.json @@ -0,0 +1,29 @@ +{ + "framework": "ripple", + "tests": [ + { + "default": { + "json_url": "/json", + "db_url": "/db", + "query_url": "/queries?queries=", + "fortune_url": "/fortunes", + "update_url": "/updates?queries=", + "plaintext_url": "/plaintext", + "port": 8080, + "approach": "Realistic", + "classification": "Fullstack", + "database": "MySQL", + "framework": "ripple", + "language": "PHP", + "flavor": "PHP8.3", + "orm": "Raw", + "platform": "ripple", + "os": "Linux", + "database_os": "Linux", + "display_name": "ripple", + "notes": "", + "versus": "php" + } + } + ] +} diff --git a/frameworks/PHP/ripple/composer.json b/frameworks/PHP/ripple/composer.json new file mode 100644 index 00000000000..fcd3f85e68e --- /dev/null +++ b/frameworks/PHP/ripple/composer.json @@ -0,0 +1,10 @@ +{ + "require": { + "ext-pdo": "*", + "cloudtay/ripple-http": "^0.3.0", + "cloudtay/ripple-rdo": "*", + "cloudtay/ripple": "^1.0@alpha" + }, + "minimum-stability": "dev", + "prefer-stable": true +} diff --git a/frameworks/PHP/ripple/fortunes.php b/frameworks/PHP/ripple/fortunes.php new file mode 100644 index 00000000000..32f765eabb6 --- /dev/null +++ b/frameworks/PHP/ripple/fortunes.php @@ -0,0 +1,18 @@ + + +Fortunes + + + + + + + + + + + + +
idmessage
+ + diff --git a/frameworks/PHP/ripple/ripple.dockerfile b/frameworks/PHP/ripple/ripple.dockerfile new file mode 100644 index 00000000000..fb521c874f4 --- /dev/null +++ b/frameworks/PHP/ripple/ripple.dockerfile @@ -0,0 +1,32 @@ +FROM php:8.3-cli + +RUN apt-get update -yqq >> /dev/null +RUN apt-get install -y libevent-dev \ + libssl-dev \ + pkg-config \ + build-essential \ + unzip >> /dev/null + +RUN docker-php-ext-install pdo_mysql \ + opcache \ + posix \ + pcntl \ + sockets >> /dev/null + +RUN pecl install event >> /dev/null + +RUN docker-php-ext-enable posix pcntl sockets +RUN docker-php-ext-enable --ini-name zz-event.ini event + +COPY --from=composer --link /usr/bin/composer /usr/local/bin/composer + +# Initialize +WORKDIR /ripple +COPY --link . . + +# Configure +RUN composer install --quiet + +# Start +EXPOSE 8080 +ENTRYPOINT ["php","server.php"] diff --git a/frameworks/PHP/ripple/server.php b/frameworks/PHP/ripple/server.php new file mode 100644 index 00000000000..8a615fb91c5 --- /dev/null +++ b/frameworks/PHP/ripple/server.php @@ -0,0 +1,200 @@ +format('D, d M Y H:i:s T'); + } + + + /** + * @return int + */ + public static function randomInt(): int + { + try { + return \random_int(1, 10000); + } catch (Throwable $e) { + return mt_rand(1, 10000); + } + } + + /** + * @param mixed $value + * + * @return int + */ + public static function clamp(mixed $value): int + { + if (!\is_numeric($value) || $value < 1) { + return 1; + } + if ($value > 500) { + return 500; + } + return \intval($value); + } + + /** + * @param string $template + * @param array $data + * + * @return string + */ + public static function render(string $template, array $data = []): string + { + foreach ($data as $key => $value) { + $$key = $value; + } + + \ob_start(); + include $template; + return \ob_get_clean(); + } +} + +$manager = new Manager(); +$worker = new class() extends \Ripple\Worker { + /*** @var \Ripple\Http\Server */ + public Server $server; + + /** + * @param \Ripple\Worker\Manager $manager + * + * @return void + */ + public function register(Manager $manager): void + { + $this->count = 64; + $this->server = new Server('http://0.0.0.0:8080'); + } + + /** + * @return void + */ + public function boot(): void + { + Setup::dateRefresh(); + repeat(static fn () => Setup::dateRefresh(), 1); + + Setup::$pdo = new \PDO( + 'mysql:host=tfb-database;port=3306;dbname=hello_world', + 'benchmarkdbuser', + 'benchmarkdbpass', + [ + \PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC, + \PDO::ATTR_EMULATE_PREPARES => false, + \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION, + ] + ); + + Setup::$queryWorldWhereID = Setup::$pdo->prepare('SELECT id, randomNumber FROM World WHERE id = ?'); + Setup::$updateWorldRandomNumber = Setup::$pdo->prepare('UPDATE World SET randomNumber = ? WHERE id = ?'); + Setup::$queryFortune = Setup::$pdo->prepare('SELECT * FROM `Fortune`'); + $this->server->onRequest(fn (Server\Request $request) => $this->onRequest($request)); + $this->server->listen(); + } + + /** + * @param \Ripple\Http\Server\Request $request + * + * @return void + */ + public function onRequest(Server\Request $request): void + { + switch ($request->SERVER['REQUEST_URI']) { + case '/json': + $request->respondJson( + ['message' => 'Hello, World!'], + ['Date' => Setup::$dateFormatted] + ); + break; + + case '/db': + $statement = Setup::$queryWorldWhereID; + $statement->execute([Setup::randomInt()]); + $request->respondJson($statement->fetch(), ['Date' => Setup::$dateFormatted]); + break; + + case '/queries': + $queries = Setup::clamp($request->GET['queries'] ?? 1); + $results = []; + $statement = Setup::$queryWorldWhereID; + while ($queries--) { + $statement->execute([Setup::randomInt()]); + $results[] = $statement->fetch(); + } + $request->respondJson($results, ['Date' => Setup::$dateFormatted]); + + break; + case '/fortunes': + $rows = Setup::$pdo->query('SELECT * FROM `Fortune`')?->fetchAll(); + $rows[] = ['id' => 0, 'message' => 'Additional fortune added at request time.']; + \usort($rows, function ($a, $b) { + return $a['message'] <=> $b['message']; + }); + + $request->respondHtml( + Setup::render('fortunes.php', ['rows' => $rows]), + [ + 'Date' => Setup::$dateFormatted, + 'Content-Type' => 'text/html; charset=UTF-8' + ] + ); + break; + + case '/updates': + $queries = Setup::clamp($request->GET['queries'] ?? 1); + $results = []; + $statement = Setup::$queryWorldWhereID; + $update = Setup::$updateWorldRandomNumber; + while ($queries--) { + $statement->execute([Setup::randomInt()]); + $row = $statement->fetch(); + $row['randomNumber'] = Setup::randomInt(); + $results[] = $row; + $update->execute([$row['randomNumber'], $row['id']]); + } + $request->respondJson($results, ['Date' => Setup::$dateFormatted]); + break; + + case '/plaintext': + $request->respond( + 'Hello, World!', + [ + 'Content-Type' => 'text/plain; charset=utf-8', + 'Date' => Setup::$dateFormatted + ] + ); + break; + + default: + $request->respond('Not Found', [], 404); + } + } +}; + +$manager->addWorker($worker); +$manager->run(); +wait(); From 6f94e080a9d6aa1dfbf49ad177c45859d12dddb5 Mon Sep 17 00:00:00 2001 From: cclilshy Date: Tue, 5 Nov 2024 12:41:21 +0800 Subject: [PATCH 2/2] [PHP/ripple] Update dependent version --- frameworks/PHP/ripple/composer.json | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/frameworks/PHP/ripple/composer.json b/frameworks/PHP/ripple/composer.json index fcd3f85e68e..679f58c8cd2 100644 --- a/frameworks/PHP/ripple/composer.json +++ b/frameworks/PHP/ripple/composer.json @@ -1,10 +1,9 @@ { "require": { "ext-pdo": "*", - "cloudtay/ripple-http": "^0.3.0", - "cloudtay/ripple-rdo": "*", - "cloudtay/ripple": "^1.0@alpha" + "cloudtay/ripple-http": "^1.0", + "cloudtay/ripple": "^1.0" }, - "minimum-stability": "dev", + "minimum-stability": "beta", "prefer-stable": true }