DbController.php 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  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. /**
  20. * @Route("/db")
  21. */
  22. public function db(): JsonResponse
  23. {
  24. return new JsonResponse($this->worldRepository->find(mt_rand(1, 10000)));
  25. }
  26. /**
  27. * @Route("/queries")
  28. */
  29. public function queries(Request $request): JsonResponse
  30. {
  31. $queries = (int) $request->query->get('queries', 1);
  32. $queries = min(max($queries, 1), 500);
  33. // possibility for enhancement is the use of SplFixedArray -> http://php.net/manual/de/class.splfixedarray.php
  34. $worlds = [];
  35. // Numbers must be unique, otherwise there is a chance to fetch twice the same number, Doctrine will then re-use
  36. // the same object and won't perform a second request which is forbidden
  37. foreach ($this->getUniqueRandomNumbers($queries) as $id) {
  38. $worlds[] = $this->worldRepository->find($id);
  39. }
  40. return new JsonResponse($worlds);
  41. }
  42. /**
  43. * @Route("/updates")
  44. */
  45. public function update(Request $request): JsonResponse
  46. {
  47. $queries = (int) $request->query->get('queries', 1);
  48. $queries = min(500, max(1, $queries));
  49. $worlds = [];
  50. // Numbers must be unique, otherwise there is a chance to fetch twice the same number, Doctrine will then re-use
  51. // the same object and won't perform a second request which is forbidden
  52. $ids = $this->getUniqueRandomNumbers($queries);
  53. // Numbers must be ordered to avoid deadlock when 2 process will update the same ids in a random order
  54. sort($ids);
  55. foreach ($ids as $id) {
  56. $worlds[] = $world = $this->worldRepository->find($id);
  57. // The new value have to be different from the previous. Otherwise Doctrine won't execute the update query
  58. // which is forbidden
  59. $oldId = $world->randomNumber;
  60. do {
  61. $newId = mt_rand(1, 10000);
  62. } while($oldId === $newId);
  63. $world->randomNumber = $newId;
  64. }
  65. $this->entityManager->flush();
  66. return new JsonResponse($worlds);
  67. }
  68. private function getUniqueRandomNumbers($count)
  69. {
  70. $res = [];
  71. $current = 0;
  72. do {
  73. for ($i=$current; $i<$count; $i++) {
  74. $res[mt_rand(1, 10000)] = 1;
  75. }
  76. } while (($current = count($res)) < $count);
  77. return array_keys($res);
  78. }
  79. }