Рубрика «идемпотентность»

Получатель записал заказ в базу, но соединение оборвалось до того, как отправитель получил ответ. Нужно ли отправлять вебхук повторно? Если не отправить, можно потерять событие. Если отправить, можно создать второй заказ.

С такого случая удобно начинать разговор о доставке. HTTP-клиент умеет сделать POST, но по таймауту не скажет, что произошло на другом конце соединения. Решать, когда повторять запрос и как обрабатывать повтор, придётся обеим сторонам.

Читать полностью »

Через год после закрытия проекта я открыл его код и устроил себе code review. Это был автомобильный маркетплейс объявлений, который я в одиночку спроектировал, написал, задеплоил и сопровождал: React‑фронтенд, три бэкенда на NestJS, PostgreSQL, чат на Socket.IO, интеграция платежей, Kubernetes в GKE, CI/CD, CronJob'ы и E2E.

Читать полностью »

Через год после закрытия проекта я открыл его код и устроил себе code review. Это был автомобильный маркетплейс объявлений, который я в одиночку спроектировал, написал, задеплоил и сопровождал: React‑фронтенд, три бэкенда на NestJS, PostgreSQL, чат на Socket.IO, интеграция платежей, Kubernetes в GKE, CI/CD, CronJob'ы и E2E.

Читать полностью »

В первом приложении мне было легко понять, чем заняться дальше. Всегда находилась ещё одна функция, которую можно добавить: новый экран, аналитика, AI, оплата. Каждая закрытая задача давала понятное ощущение прогресса. Продукт становился больше, код — сложнее, релизы — заметнее.

После большого релиза я задал себе неприятный вопрос: что именно я доказал? Что могу довести приложение до работающего состояния — да. Что людям нужна каждая из реализованных функций и они готовы возвращаться — уже не факт.

Читать полностью »

В статье разберём, почему timeout не позволяет однозначно определить результат бизнес‑операции и как безопасно обрабатывать такие ситуации.

Представим ситуацию:

  1. Наша система отправляет внешней системе запрос «Создать платёж на 50 000 ₽»
    POST /payments

  2. Внешняя система получает запрос и создаёт платёж

  3. Внешняя система отправляет ответ о созданном платеже

  4. При отправке ответа происходит ошибка и он не доходит до нашей системы

  5. Наша система не получает ответ в установленное время и фиксирует timeout

Можно ли повторить запрос на создание платежа?

Читать полностью »

Я делаю сервис по подписке и плачу налог как самозанятый. Пока подписка была бесплатной, вопросов не возникало. Как только пошли платежи, появилась обязанность, о которой мало кто думает заранее: на каждый поступивший рубль нужно выдать чек в «Мой налог», желательно в момент расчёта, а не через неделю.

Три платежа в день можно закрывать руками. Когда они приходят круглосуточно, включая четыре утра, ручная выдача превращается в постоянный риск: забыл — нарушение, выбил дважды — аннулируй и объясняйся.

Я это автоматизировал. Сама интеграция оказалась рутиной, а вот защита от второго чека на один платёжЧитать полностью »

Пятница, 23:47. PagerDuty: “Платёж AmEx, провайдер вернул 5xx три раза подряд, билеты не зарезервированы.” Открываю логи – действительно 3 ответа провайдера с 5xx, ни одной успешной транзакции по нашей базе. Закрываю как временный сбой на стороне провайдера, пишу короткую сводку в дежурный чат и иду досматривать. Через 40 минут второй алерт – уже от ночной поддержки: клиент прислал скрин выписки, 3 списания подряд за одну бронь. У клиента рейс через 6 часов, ему нужна действующая бронь и подтверждение, что он завтра нормально улетит, а не тикет в поддержку.

Читать полностью »

Вы когда-нибудь получали два списания с карты за одну покупку? Или видели дважды созданный заказ после одного клика? Это не баг платёжной системы — это баг вашего кода. Имя этому баг — отсутствие идемпотентности.


Что вообще происходит?

Представьте: пользователь нажал «Оплатить». Запрос улетел на сервер, но ответ не пришёл — таймаут. Клиент думает: «Что-то пошло не так» — и повторяет запрос. На сервере тем временем первый запрос успешно выполнился. Итог: деньги списаны дважды, пользователь в ярости, вы — на ночном дежурстве.

Или другой сценарий: Stripe отправил вам webhook payment.succeededЧитать полностью »

Всем привет! Меня зовут Наташа, и я системный аналитик. Сейчас я в поиске работы, сходила на пару собеседований, и хочу описать ответы на некоторые вопросы, которые там встречались — некая рефлексия для меня, и надеюсь, эти короткие статьи будут полезны и еще кому‑то.

Итак, кейс: 

Пользователь банка хотел перевести 100р другу, а потом нажал на кнопку «Перевести» нечаянно пять раз — как предотвратить отпра вку 5 раз по 100р?

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

Читать полностью »

Какую потенциальную проблему видите в коде?

await _applicationService.Create(application);
await _queue.Publish(new ApplicationCreatedEvent(application));

Сначала создается заявка в БД, после событие о создании отправляется в брокер сообщений(MQ) для оповещения другого сервиса о появлении новой заявки.

Здесь может произойти ошибка в момент отправки события в очередь, когда наша сущность уже создана в БД.
Это приведет к несогласованному состоянию, так как заявка будет хранится только в нашей системе, а другая система не узнает о ней.

Читать полностью »


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js