У меня есть API, который для вставки нового элемента должен быть проверен.Проверка в основном является валидатором типа (string
, number
, Date
и т. Д.) И запрашивает базу данных, которая проверяет, есть ли у «пользователя» «элемент» в ту же дату, что, если он выполняет проверку,неудачно.
Псевдокод выглядит следующим образом:
const Item = require("./models/item");
function post(newDoc){
let errors = await checkForDocErrors(newDoc)
if (errors) {
throw errors;
}
let itemCreated = await Item.create(newDoc);
return itemCreated;
}
Моя проблема в том, что если я сделаю два параллельных запроса, как это:
const request = require("superagent");
// Inserts a new Item
request.post('http://127.0.0.1:5000/api/item')
.send({
"id_user": "6c67ea36-5bfd-48ec-af62-cede984dff9d",
"start_date": "2019-04-02",
"name": "Water Bottle"
})
/*
Inserts a new Item, which shouldn't do. Resulting in two items having the
same date.
*/
request.post('http://127.0.0.1:5000/api/item')
.send({
"id_user": "6c67ea36-5bfd-48ec-af62-cede984dff9d",
"start_date": "2019-04-02",
"name": "Toothpick"
})
Оба будут успешными, чтоне должно быть, поскольку «пользователь» не может иметь два «элемента» в одну и ту же дату.
Если я выполню второй элемент после завершения первого, все будет работать, как и ожидалось.
request.post('http://127.0.0.1:5000/api/item') // Inserts a new Item
.send({
"id_user": "6c67ea36-5bfd-48ec-af62-cede984dff9d",
"start_date": "2019-04-02",
"name": "Water Bottle"
})
.then((res) => {
// It is not successful since there is already an item with that date
// as expected
request.post('http://127.0.0.1:5000/api/item')
.send({
"id_user": "6c67ea36-5bfd-48ec-af62-cede984dff9d",
"start_date": "2019-04-02",
"name": "Toothpick"
})
})
Чтобы избежать этого, я отправляю один запрос с массивом документов, но я хочу предотвратить эту проблему или, по крайней мере, снизить вероятность ее возникновения.
РЕШЕНИЕ
Я создал сервер Redis.Использовал пакет redis-lock
и обернулся вокруг POST
маршрута.
var client = require("redis").createClient()
var lock = require("redis-lock")(client);
var itemController = require('./controllers/item');
router.post('/', function(req, res){
let userId = "";
if (typeof req.body === 'object' && typeof req.body.id_user === 'string') {
userId = req.body.id_user;
}
lock('POST ' + req.path + userId, async function(done){
try {
let result = await itemController.post(req.body)
res.json(result);
} catch (e) {
res.status(500).send("Server Error");
}
done()
})
}
Спасибо.