Мобильное приложение использует сервер синтаксического анализа в качестве бэкэнда с mongoDB в качестве базы данных.
Для каждого пользователя в коллекции User есть профиль пользователя в коллекции UserProfile. Профиль пользователя имеет поле указателя как ссылку на User, которому принадлежит профиль пользователя.
Проблема в том, что во время регистрации для одного и того же пользователя создается несколько профилей пользователей.
Это потому, что процесс регистрации выглядит так:
afterSaveUserupdateProfile для обновления информации в профиле пользователяupdateProfile ищет существующий профиль пользователя или создает новый, если его нет.Это вызывает состояние гонки: сервер создает профиль пользователя на шаге # 2, и в то же время updateProfile создает новый профиль пользователя на шаге # 4. Разница во времени в createdAt этих профилей пользователей составляет миллисекунды.
В настоящее время:
Если я пропущу шаг 2, то даже если на шаге 4 вызовы будут выполняться несколько раз сразу после друг друга, это может вызвать состояние гонки, потому что updateProfile не найдет профиль пользователя, пока он не будет создан. С другой стороны, каждый пользователь должен иметь связанный с ним профиль пользователя, поэтому создание его на стороне сервера - единственный способ гарантировать это.
Если я изменю шаг № 4, чтобы не создавать новый профиль, то информация в профиле не обновляется, когда клиент вызывает функцию облачного кода updateProfile, потому что профиль пользователя из шага № 1 еще не создан.
Каков правильный подход?
beforeSaveUser, потому что у него еще нет ID. Если бы это было возможно, то было бы гарантировано создание профиля пользователя до, который клиент вызывает updateProfile.Я подумал об этом, это предотвращает создание нескольких профилей пользователей. Однако шаг №4 по-прежнему не удастся, потому что он не найдет профиль пользователя, который еще не был создан на этапе №2. Мне нужно что-то, что гарантирует, что операция записи на шаге 2 будет выполнена до операции поиска / изменения на шаге 4.
так зачем вообще делать №2? почему бы не рассчитывать на № 4, чтобы сделать работу. но вы все равно должны создать уникальный индекс.
Пожалуйста, покажите свой код. То, что вы пытаетесь сделать, легко сделать без условий гонки. Вкратце: (а) вы можете настроить хук afterSave для создания профиля и обновить и пропустить шаг 4, или (b) пропустить шаг 2 и после завершения создания пользователя вызвать updateProfile (который сначала выполнит создание, если его нет). Если один или оба этих подхода не работают, код требует проверки.
@danh (a) Перехватчик afterSave для класса User не может Обновить профиля пользователя, потому что информация для обновления предоставляется клиентом на шаге 4, поэтому шаг 4 нельзя пропустить. (b) если шаг № 2 пропущен, то создание профиля пользователя определяется клиентом. Если клиент завершает работу после запроса на создание пользователя и до ответа (например, в медленной сети), тогда профиль пользователя не будет создан. Здесь нет кода для проверки, это концептуальный вопрос.
Если профиль пользователя не создается и функция этого метода updateProfile обновляет профиль или создать, похоже, у вас нет пробелов? Я не думаю, что у вас действительно проблема.

Есть ли в UserProfile указатель на пользователя? Если это так, вы можете создать уникальный индекс для этого поля.