20 янв. 2022 г.

Различие в поведении finally между Delphi и Javascript

Пришлось потратить пару дней в поисках трудновыявимой ошибки. Все дело в том, что finally работает в Delphi и NodeJS по-разному. Будьте осторожны.

Например, в Делфи, код в секции finally выполнится ПЕРЕД окончанием выполнения функции:

function someFunc;
var
tr: TIBTransaction; 
begin
tr := TIBTransaction.Create(); 
try
... 
finally
if tr.InTransaction then
tr.Commit;
tr.Free;  
end; 
end; 

В Javascript, код в секции finally (даже не смотря на наличие await) выполнится уже ПОСЛЕ того как результат функции будет передан получателю. 

export const upsertAccount: RequestHandler = async (req, res) => {
  const { client, attachment, transaction} = await setConnection();

  try {
...
  }
  finally {
    await closeConnection(client, attachment, transaction);
  }
}; 

Теперь представим такую ситуацию. На веб сервер посылается сначала запрос на изменение данных, а после его выполнения запрос на получение (перечитывание) данных. Если мы будем делать commit транзакции в секции finally, то возможна такая ситуация, когда первый запрос уже завершится и вернет результат на клиента, который, в свою очередь, выполнит второй запрос к серверу, а транзакция все еще будет не подтверждена. В этом случае клиент получит старые данные, не соответствующие тому, что находится в базе данных.

Выход в данном случае или комитить транзакцию до секции finally, или использовать мьютекс на несколько обработчиков, который не даст прочитать данные, пока не запишется транзакция, которая меняла эти данные.


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

Отправить комментарий