Сначала я опишу сами данные и действия над ними.
Документы, хранящиеся в базе данных, объединяются с сущностью «сеанс».
Документы имеют знак сохранения IsSaved, указывая, что этот документ был сохранен.
Table Documents
{
fileGuid uuid
isSaved boolean
sessionGuid uuid
}
FrontEnd обращается к методу api асинхронно, передавая каждый документ. Логика этого метода следующая:
- Документ сохранен в хранилище файлов
- Документ помечен как сохраненный и сохранен в базе данных.
- Запрос документов сессии выполнен.
- Когда все документы в сеансе сохранены (результат == true), запускается логика для дальнейшей обработки всего сеанса:
await _fileSaver.SaveFilesAsync (fileGuid, content);
var document = await _documentStorage.GetAsync (fileGuid);
await MarkSavedAsync (sessionFile);
var result = await CheckAllSavedAsync (sessionFile.SessionGuid);
if (result)
{
...... NextProcessing (sessionFile.sessionGuid)
}
В этом случае, поскольку веб-интерфейс вызывает метод параллельно для каждого файла, то в строке 5 мы можем получить значение «true» 2 раза, а затем логика NextProcessing дублируется
Я попытался обернуть сохранение и извлечь в транзакцию с уровнем изоляции Serializable:
await _fileSaver.SaveFilesAsync (fileGuid, content);
var document = await _documentStorage.GetAsync (fileGuid);
_context.Database.BeginTransaction (isolationLevel);
await MarkSavedAsync (sessionFile);
_context.SaveChanges ();
var result = await CheckAllSavedAsync (sessionFile.SessionGuid);
_context.Database.CommitTransaction ();
if (result)
{
...... NextProcessing (sessionFile.sessionGuid)
}
Но в этом случае логично, что иногда обе транзакции в строке 9 выбирают false. И NextProcessing никогда не вызывал.
Как я могу обновить один файл набора и выбрать знак для остальных в изоляции?
пс. web-api публикуется на нескольких серверах. БД - postgres