«Иногда» дублирует вызов метода контроллера с идентичной временной меткой / датой вставки

#laravel

#laravel

Вопрос:

Я сталкиваюсь с проблемой, когда create вызывается дважды, и я не могу понять, почему. Для каждого определения a user МОЖЕТ быть несколько locations , но он должен создать только один. У меня также есть проверка для этого. Он будет owner и user из location

Созданные объекты имеют точно такую же created_at дату, но другой access_key (который создается случайным образом).

Моим первым предположением было бы то, что пользовательский интерфейс выполняет вызов дважды (из-за задержки в Интернете и двойного щелчка или чего-то в этом роде). Тем не менее, я хотел бы предотвратить дублирование серверной части.

У меня есть простое определение маршрута для создания

 Route::post('/locations', 'LocationController@create');
 

И соответствующий метод контроллера

 public function create (CreateLocationRequest $request) {
  if (Auth::user()->ownedLocations()->count() > 0) {
    return response()->json(Auth::user()->ownedLocations()->first(), 201);
  }

  $location = Auth::user()->ownedLocations()->make($request->validated());

  $access_key = rand(100000, 999999);

  while (Location::where('access_key', $access_key)->exists()) {
    $access_key = rand(100000, 999999);
  }

  $location->access_key = $access_key;
  $location->access_key_set_at = Carbon::now();

  $location->save();

  $location->users()->syncWithoutDetaching([Auth::user()->id]);

  return response()->json($location, 201);
}
 

По какой-то причине — иногда (не всегда) вызов, кажется, выполняется дважды. У меня в моей БД созданы две сущности, хотя у меня есть проверка (первая строка), которая должна получить ownedlocation и вернуть его в случае, если он уже существует.

Есть идеи?

Комментарии:

1. «Согласно определению, у пользователя МОЖЕТ быть несколько местоположений, но он должен создать только одно. У меня также есть чек на этот счет. Он будет владельцем и пользователем местоположения» Это немного сбивает с толку, и стоит разобраться, прежде чем продолжить. Каковы другие места? Кто их создает? Почему он может иметь кратные числа, но создать только одно? Может ли он отредактировать какой-либо из них?

2. Изначально планировалось, что у него может быть больше одного ребенка — теперь это должно быть ограничено. Но внесение изменений в отношения, базу данных и т.д. это займет слишком много времени, поскольку проект уже запущен. Он может прямо сейчас редактировать их и т. Д. это просто нехорошо, что он создается дважды. Поэтому я ищу способ избавиться от такого поведения. Сделать столбец уникальным было бы очевидным способом, но тогда все равно произошла бы ошибка…

3. Это не тот ответ, который вы ищете, но сложный путь работы по замене отношения взаимно однозначным, и лучшим путем для этого является исследование и разрешение двойного вызова пользовательского интерфейса. Если пользовательский интерфейс запускает два http-запроса, достаточно близких друг к другу, второй вполне может пройти проверку, которую вы установили, до того, как первый завершил запись в базу данных. Здесь трудно решить эту проблему.

4. Одна вещь, которая может помочь, — заменить метод, который вы используете для генерации access_key, на использование uuid вместо случайного числа. Используемый вами метод использует по крайней мере один запрос к базе данных, а возможно, и больше. Решение этой проблемы должно ускорить выполнение и уменьшить вероятность того, что первое сохранение не будет завершено до запуска второго.

5. Возможно, вы придаете большое значение обновлению отношений без изменения базы данных, не зная структуры вашей базы данных, но я заменил hasMany на hasOne и hasManyThrough на hasOneThrough, даже не меняя структуру таблицы. Я уверен, что вы также можете изменить belongsToMany с помощью belongsTo. Я бы посоветовал вам дважды проверить изменение отношений без изменения структуры таблицы, прежде чем снова отклонять его.