server.php 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. <?php declare(strict_types=1);
  2. include __DIR__ . '/vendor/autoload.php';
  3. use Ripple\Http\Server;
  4. use Ripple\Worker\Manager;
  5. use function Co\repeat;
  6. use function Co\wait;
  7. class Setup
  8. {
  9. public static PDO $pdo;
  10. public static string $dateFormatted;
  11. public static PDOStatement $queryWorldWhereID;
  12. public static PDOStatement $updateWorldRandomNumber;
  13. public static PDOStatement $queryFortune;
  14. public static function dateRefresh(): void
  15. {
  16. try {
  17. $date = new DateTime('now', new DateTimeZone('GMT'));
  18. } catch (Throwable $e) {
  19. return;
  20. }
  21. Setup::$dateFormatted = $date->format('D, d M Y H:i:s T');
  22. }
  23. /**
  24. * @return int
  25. */
  26. public static function randomInt(): int
  27. {
  28. try {
  29. return \random_int(1, 10000);
  30. } catch (Throwable $e) {
  31. return mt_rand(1, 10000);
  32. }
  33. }
  34. /**
  35. * @param mixed $value
  36. *
  37. * @return int
  38. */
  39. public static function clamp(mixed $value): int
  40. {
  41. if (!\is_numeric($value) || $value < 1) {
  42. return 1;
  43. }
  44. if ($value > 500) {
  45. return 500;
  46. }
  47. return \intval($value);
  48. }
  49. /**
  50. * @param string $template
  51. * @param array $data
  52. *
  53. * @return string
  54. */
  55. public static function render(string $template, array $data = []): string
  56. {
  57. foreach ($data as $key => $value) {
  58. $$key = $value;
  59. }
  60. \ob_start();
  61. include $template;
  62. return \ob_get_clean();
  63. }
  64. }
  65. $manager = new Manager();
  66. $worker = new class() extends \Ripple\Worker {
  67. /*** @var \Ripple\Http\Server */
  68. public Server $server;
  69. /**
  70. * @param \Ripple\Worker\Manager $manager
  71. *
  72. * @return void
  73. */
  74. public function register(Manager $manager): void
  75. {
  76. $this->count = 64;
  77. $this->server = new Server('http://0.0.0.0:8080');
  78. }
  79. /**
  80. * @return void
  81. */
  82. public function boot(): void
  83. {
  84. Setup::dateRefresh();
  85. repeat(static fn () => Setup::dateRefresh(), 1);
  86. Setup::$pdo = new \PDO(
  87. 'mysql:host=tfb-database;port=3306;dbname=hello_world',
  88. 'benchmarkdbuser',
  89. 'benchmarkdbpass',
  90. [
  91. \PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,
  92. \PDO::ATTR_EMULATE_PREPARES => false,
  93. \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
  94. ]
  95. );
  96. Setup::$queryWorldWhereID = Setup::$pdo->prepare('SELECT id, randomNumber FROM World WHERE id = ?');
  97. Setup::$updateWorldRandomNumber = Setup::$pdo->prepare('UPDATE World SET randomNumber = ? WHERE id = ?');
  98. Setup::$queryFortune = Setup::$pdo->prepare('SELECT * FROM `Fortune`');
  99. $this->server->onRequest(fn (Server\Request $request) => $this->onRequest($request));
  100. $this->server->listen();
  101. }
  102. /**
  103. * @param \Ripple\Http\Server\Request $request
  104. *
  105. * @return void
  106. */
  107. public function onRequest(Server\Request $request): void
  108. {
  109. switch ($request->SERVER['REQUEST_URI']) {
  110. case '/json':
  111. $request->respondJson(
  112. ['message' => 'Hello, World!'],
  113. ['Date' => Setup::$dateFormatted]
  114. );
  115. break;
  116. case '/db':
  117. $statement = Setup::$queryWorldWhereID;
  118. $statement->execute([Setup::randomInt()]);
  119. $request->respondJson($statement->fetch(), ['Date' => Setup::$dateFormatted]);
  120. break;
  121. case '/queries':
  122. $queries = Setup::clamp($request->GET['queries'] ?? 1);
  123. $results = [];
  124. $statement = Setup::$queryWorldWhereID;
  125. while ($queries--) {
  126. $statement->execute([Setup::randomInt()]);
  127. $results[] = $statement->fetch();
  128. }
  129. $request->respondJson($results, ['Date' => Setup::$dateFormatted]);
  130. break;
  131. case '/fortunes':
  132. $rows = Setup::$pdo->query('SELECT * FROM `Fortune`')?->fetchAll();
  133. $rows[] = ['id' => 0, 'message' => 'Additional fortune added at request time.'];
  134. \usort($rows, function ($a, $b) {
  135. return $a['message'] <=> $b['message'];
  136. });
  137. $request->respondHtml(
  138. Setup::render('fortunes.php', ['rows' => $rows]),
  139. [
  140. 'Date' => Setup::$dateFormatted,
  141. 'Content-Type' => 'text/html; charset=UTF-8'
  142. ]
  143. );
  144. break;
  145. case '/updates':
  146. $queries = Setup::clamp($request->GET['queries'] ?? 1);
  147. $results = [];
  148. $statement = Setup::$queryWorldWhereID;
  149. $update = Setup::$updateWorldRandomNumber;
  150. while ($queries--) {
  151. $statement->execute([Setup::randomInt()]);
  152. $row = $statement->fetch();
  153. $row['randomNumber'] = Setup::randomInt();
  154. $results[] = $row;
  155. $update->execute([$row['randomNumber'], $row['id']]);
  156. }
  157. $request->respondJson($results, ['Date' => Setup::$dateFormatted]);
  158. break;
  159. case '/plaintext':
  160. $request->respond(
  161. 'Hello, World!',
  162. [
  163. 'Content-Type' => 'text/plain; charset=utf-8',
  164. 'Date' => Setup::$dateFormatted
  165. ]
  166. );
  167. break;
  168. default:
  169. $request->respond('Not Found', [], 404);
  170. }
  171. }
  172. };
  173. $manager->addWorker($worker);
  174. $manager->run();
  175. wait();