Рубрика «saga»

Если вы работаете с одной базой данных которая поддерживает транзакции вы даже не задумываетесь о консистентности — база все делает за вас. Если же у вас несколько баз, распределенная система или даже к примеру MongoDB до 4 версии — все не так радужно.

Рассмотрим пример — мы хотим сохранить файл в хранилище и добавить ссылку на него в два документа. Конечно же мы хотим атомарности — либо файл сохранен и добавлен в документы либо ни то ни другое (тут и далее используется cats-effects IO):

saveDataToFile(data) // (1)
  .flatMap { file =>
    addFileRef(documentId, file) // (2)
      .flatMap { result =>
        addFileRef(fileRegistry, file) // (3)
          .flatMap { result =>
            ??? // (4, 5, ...)
          }
          .handleErrorWith { error =>
            // revert (2)
            removeFileRef(documentId, file).attempt >> IO.raiseError(error)
          }
      }
      .handleErrorWith { error =>
        // revert (1)
        removeFile(file).attempt >> IO.raiseError(error)
      }
  }

Уже непросто? Легко представить как количество операций растет и образуется Pyramid of doom.

Но мы же программисты! Давайте обобщим проблему и напишем код, который позволит избежать ненужной сложности и возможных ошибок.

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

Все, кто работает с Redux, рано или поздно сталкиваются с проблемой асинхронных действий. Но современное приложение разработать без них невозможно. Это и http-запросы к бэкенду, и всевозможные таймеры/задержки. Сами создатели Redux говорят однозначно — по умолчанию поддерживается только синхронный data-flow, все асинхронные действия необходимо размещать в middleware.

Конечно, это слишком многословно и неудобно, поэтому тяжело найти разработчика, который пользуется одними только “нативными” middleware. На помощь всегда приходят библиотеки и фреймворки, такие как Thunk, Saga и им подобные.

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

async dispatch => {
   setTimeout(() => {
      try {
         await Promise
            .all([fetchOne, fetchTwo])
            .then(([respOne, respTwo]) => {
                dispatch({ type: 'SUCCESS', respOne, respTwo });
             });
      } catch (error) {
          dispatch({ type: 'FAILED', error });
      }   
   }, 2000);
}

На такой код больно даже смотреть, а поддерживать и расширять просто невозможно. Что делать, когда нужна более сложная обработка ошибки? А вдруг понадобится повтор запроса? А если я захочу переиспользовать эту функцию?

Меня зовут Дмитрий Самохвалов, и в этом посте я расскажу, что такое концепция Observable и как применять её на практике в связке с Redux, а еще сравню всё это с возможностями Redux-Saga.
Читать полностью »

Проблематика

Практически любая информационная система требует хранения данных на постоянной основе. В большинстве систем с малой и средней нагрузкой эту функцию выполняют реляционные СУБД, неоспоримым преимуществом которых является гарантия согласованности данных.

Классический пример, объясняющий, что такое согласованность данных – операция перевода денежных средств с одного счёта на другой. В момент, когда операция изменения баланса одного счёта уже выполнилась, а другого – ещё не успела, может произойти сбой. Тогда с одного счёта средства будут списаны, а на другой не поступят. Такое состояние данных системы называется рассогласованным, и, пожалуй, нет необходимости объяснять, к каким последствиям это может привести. Реляционные СУБД предоставляют механизм транзакций, гарантирующий согласованность данных в любой момент времени. Транзакция – это конечный набор операций, который переводит одно согласованное состояние в другое согласованное состояние. Читать полностью »

15 сентября в офисе Авито состоится встреча, посвященная масштабированию приложений на PostgreSQL. Поговорим об алгоритмах и нюансах реализации транзакционности в языках программирования, построении бизнес-транзакций в сервисах с паттерном database per service, как устроена OZO — асинхронная типобезопасная header-only библиотека-клиент PostgreSQL для C++17, и уровнях изоляции транзакций PostgreSQL. С докладами выступят Стас Кельвич (Postgres Professional), Сергей Хандриков (Яндекс), Константин Евтеев (Авито) и Михаил Тюрин. Регистрируйтесь на встречу и приглашайте коллег. Под катом — тезисы выступлений докладчиков, ссылка на регистрацию и информация по трансляции митапа.

image

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

Привет! Меня зовут Константин Евтеев, я работаю в Авито руководителем юнита DBA. Наша команда развивает системы хранения данных Авито, помогает в выборе или выдаче баз данных и сопутствующей инфраструктуры, поддерживает Service Level Objective для серверов баз данных, а еще мы отвечаем за эффективность использования ресурсов и мониторинг, консультируем по проектированию, а возможно и разрабатываем микросервисы, сильно завязанные на системы хранения, или сервисы для развития платформы в контексте хранилищ.

Я хочу рассказать, как мы решили один из вызовов микросервисной архитектуры — проведение бизнес-транзакций в инфраструктуре сервисов, построенных с помощью паттерна Database per service. С докладом на эту тему я выступал на конференции Highload++ Siberia 2018.

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


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