Итак, у меня есть сервер Node.js, и я использую экспресс для маршрутизации. Допустим, у меня есть маршрут для обработки запросов POST, который состоит в основном из асинхронных функций (async / await) . Маршрут служит для создания учетной записи пользователя (вставка строки в базу данных Postgresql). Каждый аккаунт должен иметь уникальный адрес электронной почты. Когда я получаю запрос, первое, что делает маршрут, это запрос инструкции SELECT к БД, чтобы проверить, существует ли учетная запись с предоставленной электронной почтой - если это так, сервер отвечает определенным кодом статуса http и, если нет, новымАккаунт вставлен в БД. Это выглядит так:
var { data } = await selectAccount(email);
if (data) {
return res.status(400).send({ "info": "Email already in use" });
} else {
await insertAccount(email);
return res.sendStatus(200);
}
Проблема в том, что, когда я получаю два или более запросов с одним и тем же письмом, с разницей всего в несколько миллисекунд. Если разница во времени между запросами составляет около 100 мс или более, все идет хорошо. Но с такой небольшой разницей во времени между запросами (скажем, 5 или 10 мс) код выполняется почти одновременно, поэтому select в обоих запросах не возвращает данных, и в БД вставляются две учетные записи с одинаковым адресом электронной почты.
Oneодним из способов решения этой проблемы будет установка уникального ограничения на электронную почту в базе данных, но я не хочу этого делать, потому что: 1. Я хочу изучить другие правильные способы решения этой проблемы, 2. Обработка исключений из БД и реагирование с определенным httpКоды состояния не всегда так просты, 3. Я имею дело с этой проблемой и на других маршрутах, где установка уникального ограничения невозможна.
Я думал об использовании async.queue, но я делаюНЕ хочу ставить запросы в очередь, только конкретные запросы с одинаковым телом (в данном случае с электронной почтой), и я не думаю, что для этого предназначен async.queue.
Другая вещь - использование Redis - но если запросыс разницей всего в несколько мс, Redis тоже может выйти из строя.
Я также искал решение, связанное с usiВ случае мьютекса, но безуспешно, поскольку реализации мьютекса принесли много сложностей. Спасибо за любую помощь
Правка (добавление функций - я использую модуль pg
для объединения):
async function selectAccount(email) {
var sql = "SELECT email FROM account WHERE email = $1";
try {
var { rows } = await pool.query(sql, [email]);
} catch (err) {
Log.e(err);
return { data: new Error(JSON.stringify(err)) };
}
return { data: rows };
}
async function insertAccount(email) {
var sql = "INSERT INTO account ( email ) VALUES ( $1 )";
try {
await pool.query(sql, [email]);
} catch (err) {
Log.e(err);
}
return;
}
Примечание: я не закончил свою работу, поэтому яулучшит обработку ошибок.