мета-данные страницы
Это старая версия документа!
Идемпотентность запросов
Можно ознакомится со статьей от Яндекс: https://habr.com/ru/company/yandex/blog/442762/
Обработка в агенте
Обработка на клиенте
Пример МП Courier
1. Пишущая транзакция (на сервере)
Обработка в агенте
- Добавлены property
- Himstat.IdempotencyText устанавливается на прямую (доступно на чтение и запись)
- Himstat.IdempotencyHash устанавливается при установке IdempotencyText (доступно только на чтение)
- uErrorRes добавлен тип Exception TIdenpotencyException
- На примере запроса PayPlanOrders:
- THimstatDM.ReplyWithPayPlanOrders
- Himstat.IdempotencyText := Srvr.Request.Query.Text; Получаем IdempotencyText IdempotencyHash
- Himstat.DoPayPlanOrders
- QueryIdempotency Записываем в таблицу Hash и время
- Нет таблицы IDEMPOTENCY_QUERY - выходим из проверки
- получаем старый ОТВЕТ (предыдущего АНАЛОГИЧНОГО запроса) ИЛИ получаем ОТВЕТ=«» - Идет запись
- ОТВЕТ=null - пытаемся записать HASH
- ERROR Присваиваем ОТВЕТ:=«» - Идет запись
- FINALY
- (1) ЕСЛИ ОТВЕТ=null - то у нас уникальный запрос записанный в таблицу
- (2) ЕСЛИ ОТВЕТ<>null - запрос не уникален - возбуждаем исключение TIdenpotencyException.Create(ОТВЕТ);
- (1) UpdateIdempotency сохраняем ОТВЕТ в таблицу
- (2) TIdenpotencyException
- Если исключение содержит НЕ ПУСТОЕ сообщение то это ОТВЕТ и мы его отправляем повторно
- Если исключение содержит ПУСТОЕ сообщение то снова возбуждаем TIdenpotencyException и отправляем как ошибку ОДНОВРЕМЕННОГО ЗАПРОСА (ErrorCode = 5)
- Если ОШИБКА произошла в теле обработки до сохранения ОТВЕТа то HASH запроса удаляется
Клиент
- Организовать уникальность запроса
- Обработку ErrorCode = 5
Обработка на клиенте
Пример МП Courier
... ... var PayIdempotency: string;/ /'Переменная сохраняет состояние текущей транзакции /запрос(dor_id, debet) + ответ(JSON)/' ... ... JSONAnswer := KassaFiscalRegistar.PrintFiscalCheck(JSONResultObj); / /'Печать чека' ... except on E: Exception do begin PayIdempotency := ''; / /'Если ошибка при печати - обнуляем текущую транзакцию' ... ... procedure TmoneyPayFramePanel.OnShow(curVisible: TuniFramePanel); begin PayIdempotency := '';/ / 'При входе обнуление предыдущей транзакции' ... ... ClnDM.GetFiscalCheck(sJSON, procedure (AJObject: TJSONObject) var CurrentPayIdempotency: string; / /'Текущая транзакция' begin CurrentPayIdempotency := THashMD5.GetHashString(sJSON + '=' + AJObject.ToString); if PayIdempotency = CurrentPayIdempotency then / /'Текущую сравниваем с запомненой' begin / / 'Ничего не делаем если транзакция все еще ТА ЖЕ' WriteLog("TmoneyPayFramePanel.WorkOfPay PayIdempotency = CurrentPayIdempotency Abort"); end else begin / /'Транзакция другая - выпонить оплату' PayIdempotency := CurrentPayIdempotency; AnswerFromWeb('GetFiscalCheck', '', 0, AJObject); end; end); ... ...