DbController.php 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. <?php
  2. namespace App\Controller;
  3. use App\Repository\WorldRepository;
  4. use Doctrine\ORM\EntityManagerInterface;
  5. use Symfony\Component\HttpFoundation\JsonResponse;
  6. use Symfony\Component\HttpFoundation\Request;
  7. use Symfony\Component\Routing\Annotation\Route;
  8. class DbController
  9. {
  10. /** @var EntityManagerInterface */
  11. private $entityManager;
  12. /** @var WorldRepository */
  13. private $worldRepository;
  14. public function __construct(EntityManagerInterface $entityManager, WorldRepository $worldRepository)
  15. {
  16. $this->entityManager = $entityManager;
  17. $this->worldRepository = $worldRepository;
  18. }
  19. #[Route('/db')]
  20. public function db(): JsonResponse
  21. {
  22. return new JsonResponse($this->worldRepository->find(mt_rand(1, 10000)));
  23. }
  24. #[Route('/queries')]
  25. public function queries(Request $request): JsonResponse
  26. {
  27. $queries = (int) $request->query->get('queries', 1);
  28. $queries = min(max($queries, 1), 500);
  29. // possibility for enhancement is the use of SplFixedArray -> http://php.net/manual/de/class.splfixedarray.php
  30. $worlds = [];
  31. // Numbers must be unique, otherwise there is a chance to fetch twice the same number, Doctrine will then re-use
  32. // the same object and won't perform a second request which is forbidden
  33. foreach ($this->getUniqueRandomNumbers($queries) as $id) {
  34. $worlds[] = $this->worldRepository->find($id);
  35. }
  36. return new JsonResponse($worlds);
  37. }
  38. #[Route('/updates')]
  39. public function update(Request $request): JsonResponse
  40. {
  41. $queries = (int) $request->query->get('queries', 1);
  42. $queries = min(500, max(1, $queries));
  43. $worlds = [];
  44. // Numbers must be unique, otherwise there is a chance to fetch twice the same number, Doctrine will then re-use
  45. // the same object and won't perform a second request which is forbidden
  46. $ids = $this->getUniqueRandomNumbers($queries);
  47. // Numbers must be ordered to avoid deadlock when 2 process will update the same ids in a random order
  48. sort($ids);
  49. foreach ($ids as $id) {
  50. $worlds[] = $world = $this->worldRepository->find($id);
  51. // The new value have to be different from the previous. Otherwise Doctrine won't execute the update query
  52. // which is forbidden
  53. $oldId = $world->randomNumber;
  54. do {
  55. $newId = mt_rand(1, 10000);
  56. } while($oldId === $newId);
  57. $world->randomNumber = $newId;
  58. }
  59. $this->entityManager->flush();
  60. return new JsonResponse($worlds);
  61. }
  62. private function getUniqueRandomNumbers($count)
  63. {
  64. $res = [];
  65. $current = 0;
  66. do {
  67. for ($i=$current; $i<$count; $i++) {
  68. $res[mt_rand(1, 10000)] = 1;
  69. }
  70. } while (($current = count($res)) < $count);
  71. return array_keys($res);
  72. }
  73. }