Штрафы тоже так себе решение. Недавняя история со Сбербанком тому показатель. Был слив персональных данных всех региональных сотрудников. Так просто Сбербанк ответил, что данные не являются персональными и поэтому проблемы нет. Нет проблемы — нет штрафа.
Согласен. Не стоит всё доводить до абсурда, в том числе и дробление модели состояний.
В вашем примере уже фигурирует before, after, in_progress что само по себе уже явно намекает, что так дробить состояния не нужно и пора бы уже остановиться.
В примере выше — две независимые бизнес-логики тем более общающиеся (скорее всего) с разными внешними системами.
Тут можно решение обыграть через бронирование.Т.е. перед оплатой бронируется позиция на складе, идет оплата, бронь подтверждается. При таком подходе у системы шансов больше выжать и не потерять заказ (и товар).
переход должен проходить автоматически, т.е. сервис после восстановления работы должен сам решать такие кейсы
Если такое требование есть — то, возможно, лучшим решением будет использовать BPMN движки или Саги.
Бывает, что достаточно фонового процесса следящего за «подвисшими» сущностями и запускающий альтернативную цепочку состояний.
В вашем случае можно (нужно) декомпозировать модель состояний. Т.е. «деньги списаны» и «запрос доставлен в службу доставки» должны быть разными состояниями со своими переходами и логикой.
Если я правильно вас понял, то на одно состояние у вас завязаны две независимые логики, что не есть хорошо.
На самом деле вероятность очень маленькая. Например, по расчетам будущего столкновения Млечного Пути и Андромеды (через 4 миллиарда лет) непосредственно столкновений между звездами будет очень мало (доли процентов). Основное влияние — через гравитационные возмущения. Были статьи на WIKI и на Хабр по этому поводу.
Правильно ли я понимаю, что если настроить на телефоне выход в интернет через VPN, то никаких платных подписок через «левые» сайты уже не будет? Ведь если телефон идет через VPN, то даже при приходе на левый сайт ОПСОС не сможет «подкинуть» в заголовки номер телефона.
Сегодня, 13 апреля 2018 года, состоялся официальный анонс игрового смартфона Xiaomi Black Shark, одной из ключевых особенностей которого стала система жидкостного охлаждения.
Лично много раз наблюдал как старую историческую каменную кладку прослужившую более 100 лет разбирали чтобы построить забор генералам, а на её место заливали асфальт тающий на следующий год. И плотины. Под Питером их много было небольших, есть и те которые лично Петр закладывал. И многие из них разобрали местные по дачам.
Моя бабушка вполне себе сушила вещи на морозе. Когда мне было около 10 лет я тоже попробовал, но не очень удачно. После втряхивания вместо одной рубашки у меня в руках оказалось две. С тех пор не проверял действительно ли вода с твердого состояния испаряется или нет.
Многие уже ответили, но есть еще один критичный для некоторый момент — это выезд/приезд из центра одного города сразу в центр другого. Это может экономить очень много времени.
Если Чёрная Африка займётся вложениями в молодёжь, регион сможет удвоить свою долю в глобальной рабочей силе к 2050 году, и обеспечить лучшую жизнь для сотен миллионов людей.
Хм. По мне звучит как неприкрытая пропаганда рабства. Одно государство должно вкладываться чтобы удвоить рабочую силу в других государствах и этим самым обеспечить лучшую жизнь для сотен миллионов других людей, не выходцев из Черной Африки.
Хотя может быть это просто особенность перевода.
Проблема в том, что клиент никакого профита не получил. Сидели у него менеджеры без сервиса, и справлялись с потоком заказов. Теперь справляется сервис, а менеджеры все равно сидят. С точки зрения руководителя и собственника никаких изменений не произошло. Только деньги зря отдали за разработку.
Если автоматизация позволила увеличить поток заказов за счет того, что заказы обрабатываются не вручную, то 1) изменения произошли, 2) они осязаемы (исчисляемы), 3) деньги не были отданы зря за разработку. Ну и как бонус этим менеджерам теперь можно найти другую работу пользы собственника для.
Это происходит потому, что этот RPC с большей вероятностью не добавят, нежели добавят.
В результате в микросервисной архитектуре разработчики более склонны искать способы решить проблему используя уже существующее API
Вы всё верно говорите. Но стоит учесть человеческий фактор — лень и стремление делать меньше. И поэтому частенько вижу и отклоняю желания разработчиков сделать generic API вида get_all / update (eval) как подсказал amarao.
И такое происходит сплошь и рядом. И если за этим не следить (привет микросервисные Архитекторы), то «комок грязи» быстро дает о себе знать.
Хорошая тема поднята, интересная. К сожалению ни одна известная мне спецификация не закрывает все поднятые в статье вопросы.
Для того чтобы эту тему закрыть в своих проектах мы ориентируемся на следующие моменты:
HTTP Status — какие коды использовать в каких случаях
HTTP BODY (json, xml — не суть важно) — формат ответа
Подсистема мониторинга — выявление и реагирование на ошибки
UI и взаимодействие с пользователем
Цепочка ответственности
Troubleshooting Guide
Логирование
1. HTTP Status
200 — для ответов которые выполнились без ошибок.
Из этого правила есть исключения. Например:
Если сущность версионируемая и хоть обработка запроса была с ошибкой, но привела к смене версии объекта (т.е. он был изменен). В этом случае в теле ответа возвращается детальная информация что именно пошло не так и как реагировать на это вызываемой стороне.
Либо если это был batch-запрос который не покрыт единой транзакцией и часть данных этого запроса не была корректно обработана. В этом случае в теле ответа возвращается список ошибок с информацией какой именно набор подзапросов не был обработан и почему.
2. HTTP BODY
Для 200 — тело достаточно разнообразное, сообразно задаче. Если глобально поделить, то это:
запрашиваемые данные
для листовых результатов — обрамляющая структура в которую входит мета-данные (например с информацией о постраничном доступе к данным), сами запрашиваемые данные
для командных запросов — либо полный набор данных по которым была команда, либо DIFF (только тот набор данных, которые были реально изменены этой командой)
3. Подсистема мониторинга
Т.к. наличие такой подсистемы сильно облегчаешь жизнь на продакшене и не только, то лучше ей не мешать работать, но помогать.
Если на все ответы отдавать 200-й код и «скрывать» реальную ситуацию (хорошо / ошибка) в теле ответа, то обычно подсистема мониторинга будет бессильна вам помочь и это плохо.
Поэтому совет простой — если произошла ошибка на которую нужно среагировать (не обязательно прямо в момент ее появления, но и отложено, ретроспективно )- то не используйте 200-й код для этого. Люди, которые буду сопровождать систему на проде будут вам благодарны.
4. UI и взаимодействие с пользователем
Мы ведь все не только разработчики, но и пользователи информационных систем. И понимаем, что выгружать на пользователя стек ошибки исполнения, детальную информацию о падении и прочим не хорошо. Но если что-то пошло не так, то до пользователя нужно эту информацию донести. Формат jsonapi.org/examples/#error-objects очень не плохо с этим помогает.
Тем более в ситуации когда UI должен поддерживать различные локали (i18n).
А, учитывая, что при успешном исполнении запроса что-то могло пойти не так, но система с этим справилась — тоже бывает важно показать пользователю. Пример:
Заказ проведен, но бронь не удалось сделать. Если бронь не прошла (не доступен был сервис), то это не повод не попытаться взять денег с пользователя :)
5. Цепочка ответственности
Не увидел в теме и в комментариях момента когда запрос делается не с UI, а с промежуточного, например, микросервиса и ему приходит ошибка. В этом случае важно не потерять информацию об оригинальном месте и причине ошибки, но донести ее до инициатора бизнес-запроса в исходном виде добавив к ней ту информацию с текущего контекста исполнения которая может быть полезна для принятия решения как на ошибку реагировать.
Плюс унифицированный формат ответов в случае ошибок очень сильно упрощает их обработку и пересылку.
6. Troubleshooting Guide
Ну с этим, думаю все понятно. С одной стороны мы должны выдать минимум информации (код ошибки), с другой стороны по этому коду ошибки должны получить максимум информации чтобы среагировать на неё.
Обычно для этого вводят коды ошибок. Для упрощения восприятия их можно объединять в группы, пример:
0000 — это ОК, все хорошо
0001 — 1999 — набор валидационных ошибок
2000 — 4999 — группа бизнес ошибок
5000 — 7999 — интеграционные ошибки и ошибки доступа к данным
Вариантов группировок — на вкус и цвет :)
7. Логирование
Сама по себе большая и не однозначная тема. Но ошибки надо легировать — это факт.
И наличие в них кода ошибки упростит их поиск. Для того, чтобы вычленить всю цепочку лог-записей приведших к ошибке используется трассировка записей (например по x-request-id).
-----
Прошу прощения если получилось несколько сумбурно. В целом каждый пункт, это по факту не маленький документ являющийся технической спецификацией от которой отталкиваются разработчики при работе над Проектом. По которому создаются интеграционные тесты и прочее.
Для таких моментов есть разные варианты решений, каждый из них имеет как преимущества, так и недостатки. Всё нужно оценивать и выбирать исходя из полных требований.
Примеры решения:
Введение reference сущности которая является immutable и реплицируется на все ноды. Т.к. в реальности immutablе редко достижим, то вводятся объекты с указанным временем жизни (active_from / active_to например). Соответственно join операции проводятся локально по данным одной ноды.
Вводится дополнительная агрегирующая сущность в которую реплицируется полный необходимый набор данных с других нод. И далее логика работы идет над этим срезом данных. Здесь имеется большая избыточность, но и плюсы есть (например жесткая фиксация контракта, цен и прочее. Такой вариант версионирования когда мастер данные можно менять не боясь сломать активный текущий процесс.
Организуется MapReduce подход или его аналог
В зависимости от требований и технических особенностей хранилища данных возможны и другие варианты
В вашем примере уже фигурирует before, after, in_progress что само по себе уже явно намекает, что так дробить состояния не нужно и пора бы уже остановиться.
В примере выше — две независимые бизнес-логики тем более общающиеся (скорее всего) с разными внешними системами.
Тут можно решение обыграть через бронирование.Т.е. перед оплатой бронируется позиция на складе, идет оплата, бронь подтверждается. При таком подходе у системы шансов больше выжать и не потерять заказ (и товар).
Если такое требование есть — то, возможно, лучшим решением будет использовать BPMN движки или Саги.
Бывает, что достаточно фонового процесса следящего за «подвисшими» сущностями и запускающий альтернативную цепочку состояний.
Если я правильно вас понял, то на одно состояние у вас завязаны две независимые логики, что не есть хорошо.
Хм. По мне звучит как неприкрытая пропаганда рабства. Одно государство должно вкладываться чтобы удвоить рабочую силу в других государствах и этим самым обеспечить лучшую жизнь для сотен миллионов других людей, не выходцев из Черной Африки.
Хотя может быть это просто особенность перевода.
Если автоматизация позволила увеличить поток заказов за счет того, что заказы обрабатываются не вручную, то 1) изменения произошли, 2) они осязаемы (исчисляемы), 3) деньги не были отданы зря за разработку. Ну и как бонус этим менеджерам теперь можно найти другую работу пользы собственника для.
Вы всё верно говорите. Но стоит учесть человеческий фактор — лень и стремление делать меньше. И поэтому частенько вижу и отклоняю желания разработчиков сделать generic API вида get_all / update (eval) как подсказал amarao.
И такое происходит сплошь и рядом. И если за этим не следить (привет микросервисные Архитекторы), то «комок грязи» быстро дает о себе знать.
Для того чтобы эту тему закрыть в своих проектах мы ориентируемся на следующие моменты:
1. HTTP Status
200 — для ответов которые выполнились без ошибок.
Из этого правила есть исключения. Например:
Если сущность версионируемая и хоть обработка запроса была с ошибкой, но привела к смене версии объекта (т.е. он был изменен). В этом случае в теле ответа возвращается детальная информация что именно пошло не так и как реагировать на это вызываемой стороне.
Либо если это был batch-запрос который не покрыт единой транзакцией и часть данных этого запроса не была корректно обработана. В этом случае в теле ответа возвращается список ошибок с информацией какой именно набор подзапросов не был обработан и почему.
2. HTTP BODY
Для 200 — тело достаточно разнообразное, сообразно задаче. Если глобально поделить, то это:
В случае ошибок стараемся придерживаться вот этого описания:
jsonapi.org/examples/#error-objects
3. Подсистема мониторинга
Т.к. наличие такой подсистемы сильно облегчаешь жизнь на продакшене и не только, то лучше ей не мешать работать, но помогать.
Если на все ответы отдавать 200-й код и «скрывать» реальную ситуацию (хорошо / ошибка) в теле ответа, то обычно подсистема мониторинга будет бессильна вам помочь и это плохо.
Поэтому совет простой — если произошла ошибка на которую нужно среагировать (не обязательно прямо в момент ее появления, но и отложено, ретроспективно )- то не используйте 200-й код для этого. Люди, которые буду сопровождать систему на проде будут вам благодарны.
4. UI и взаимодействие с пользователем
Мы ведь все не только разработчики, но и пользователи информационных систем. И понимаем, что выгружать на пользователя стек ошибки исполнения, детальную информацию о падении и прочим не хорошо. Но если что-то пошло не так, то до пользователя нужно эту информацию донести. Формат jsonapi.org/examples/#error-objects очень не плохо с этим помогает.
Тем более в ситуации когда UI должен поддерживать различные локали (i18n).
А, учитывая, что при успешном исполнении запроса что-то могло пойти не так, но система с этим справилась — тоже бывает важно показать пользователю. Пример:
Заказ проведен, но бронь не удалось сделать. Если бронь не прошла (не доступен был сервис), то это не повод не попытаться взять денег с пользователя :)
5. Цепочка ответственности
Не увидел в теме и в комментариях момента когда запрос делается не с UI, а с промежуточного, например, микросервиса и ему приходит ошибка. В этом случае важно не потерять информацию об оригинальном месте и причине ошибки, но донести ее до инициатора бизнес-запроса в исходном виде добавив к ней ту информацию с текущего контекста исполнения которая может быть полезна для принятия решения как на ошибку реагировать.
Плюс унифицированный формат ответов в случае ошибок очень сильно упрощает их обработку и пересылку.
6. Troubleshooting Guide
Ну с этим, думаю все понятно. С одной стороны мы должны выдать минимум информации (код ошибки), с другой стороны по этому коду ошибки должны получить максимум информации чтобы среагировать на неё.
Обычно для этого вводят коды ошибок. Для упрощения восприятия их можно объединять в группы, пример:
0000 — это ОК, все хорошо
0001 — 1999 — набор валидационных ошибок
2000 — 4999 — группа бизнес ошибок
5000 — 7999 — интеграционные ошибки и ошибки доступа к данным
Вариантов группировок — на вкус и цвет :)
7. Логирование
Сама по себе большая и не однозначная тема. Но ошибки надо легировать — это факт.
И наличие в них кода ошибки упростит их поиск. Для того, чтобы вычленить всю цепочку лог-записей приведших к ошибке используется трассировка записей (например по x-request-id).
-----
Прошу прощения если получилось несколько сумбурно. В целом каждый пункт, это по факту не маленький документ являющийся технической спецификацией от которой отталкиваются разработчики при работе над Проектом. По которому создаются интеграционные тесты и прочее.
Примеры решения:
Судя по этому, да, автор считает что логирование в ERROR уровне = факту обработки этой ошибки. Думаю многие склоны с ним не согласиться.