From 9a3b923e7ff1fde9d0c6da5a9f53ce12b957a07e Mon Sep 17 00:00:00 2001 From: Stas Date: Fri, 20 Mar 2026 11:35:07 +0300 Subject: [PATCH] feat: add lab-01 report for Mihnovec Stanislav --- students/Mihnovec_Stas/lab-01/analysis.md | 39 +++ .../lab-01/diagrams/sequence-error.png | Bin 0 -> 38904 bytes .../lab-01/diagrams/sequence-error.puml | 35 +++ .../lab-01/diagrams/sequence-happy.png | Bin 0 -> 43641 bytes .../lab-01/diagrams/sequence-happy.puml | 42 ++++ .../Mihnovec_Stas/lab-01/scenarios.feature | 37 +++ students/Mihnovec_Stas/lab-01/use-case.md | 43 ++++ ...20\236\321\202\321\207\320\265\321\202.md" | 231 ++++++++++++++++++ students/students.csv | 1 + .../examples/diagrams/sequence-happy.puml | 2 +- 10 files changed, 429 insertions(+), 1 deletion(-) create mode 100644 students/Mihnovec_Stas/lab-01/analysis.md create mode 100644 students/Mihnovec_Stas/lab-01/diagrams/sequence-error.png create mode 100644 students/Mihnovec_Stas/lab-01/diagrams/sequence-error.puml create mode 100644 students/Mihnovec_Stas/lab-01/diagrams/sequence-happy.png create mode 100644 students/Mihnovec_Stas/lab-01/diagrams/sequence-happy.puml create mode 100644 students/Mihnovec_Stas/lab-01/scenarios.feature create mode 100644 students/Mihnovec_Stas/lab-01/use-case.md create mode 100644 "students/Mihnovec_Stas/lab-01/\320\236\321\202\321\207\320\265\321\202.md" diff --git a/students/Mihnovec_Stas/lab-01/analysis.md b/students/Mihnovec_Stas/lab-01/analysis.md new file mode 100644 index 00000000..b3fb194c --- /dev/null +++ b/students/Mihnovec_Stas/lab-01/analysis.md @@ -0,0 +1,39 @@ +# Анализ границ ответственности и обработка исключений + +## Транзакционные границы +Транзакция начинается в момент получения API-запроса от пользователя на создание жалобы. Она включает в себя проверку существования новости, проверку на дубликаты (идемпотентность) и запись в БД. Вызов внешнего сервиса модерации вынесен за рамки строгой БД-транзакции во избежание блокировок при таймаутах. + +| Операция | Тип (Sync/Async) | Откат при ошибке | Стратегия повтора (Retry) | Идемпотентность | +|----------|------------------|------------------|---------------------------|-----------------| +| Сохранение жалобы в БД | Синхронная | Да (БД транзакция ROLLBACK) | Нет | Да (Ключ: `user_id` + `news_id`) | +| Проверка через AI Moderation | Синхронная (с коротким таймаутом) | Нет (Переход в Async) | Отправка в очередь RabbitMQ с экспоненциальной задержкой | Да (Сервис ИИ кэширует хеш текста) | +| Уведомление модераторов (Email) | Асинхронная | Нет (best-effort) | 3 попытки (через брокер сообщений) | Да (дедупликация по `complaint_id`) | +| Скрытие новости (если 100% фейк)| Асинхронная | Нет | Retry до победного (Dead Letter Queue) | Да (Проверка текущего статуса новости) | + +--- + +## Обработка исключительных ситуаций + +### 1. Исключительная ситуация: Таймаут сервиса Автомодерации (AI Checker) + +**Условие**: Внешний сервис HTTP POST `/analyze` не отвечает более 3 секунд. +**Обнаружение**: HTTP-клиент (например, Axios или HttpClient) выбрасывает `TimeoutException`. +**Реакция**: +1. Система не прерывает процесс создания жалобы. +2. Жалоба фиксируется в БД со статусом `PENDING` (Ожидает обработки). +3. Событие отправляется в очередь (RabbitMQ/Kafka) для фоновой обработки. +**Компенсация**: Компенсация не требуется, так как транзакция в БД успешна. Задача будет выполнена позже воркером. +**Уведомление пользователя**: "Жалоба принята. Из-за высокой нагрузки проверка займет чуть больше времени." + +### 2. Исключительная ситуация: Нарушение уникальности (Race Condition / Double Click) + +**Условие**: Пользователь дважды нажимает кнопку "Отправить", генерируя два одновременных запроса. +**Обнаружение**: База данных выбрасывает `UniqueConstraintViolationException` (уникальный индекс на `user_id` + `news_id`). +**Реакция**: +1. Первый запрос проходит успешно. +2. Второй запрос перехватывает ошибку уникальности. +**Компенсация**: Откат транзакции второго запроса. +**Уведомление пользователя**: "Ваша жалоба уже была принята ранее." (возвращается успешный ответ, чтобы не пугать пользователя ошибкой 500). + +### 3. Бонус: Реализация паттерна Circuit Breaker +Для защиты системы от каскадных сбоев, если сервис AI-модерации лежит полностью (ошибки 5xx подряд), система открывает Circuit Breaker. Запросы перестают отправляться во внешний сервис и **сразу** складываются в RabbitMQ, что экономит 3 секунды ожидания таймаута на каждом запросе пользователя, сохраняя отзывчивость UI. \ No newline at end of file diff --git a/students/Mihnovec_Stas/lab-01/diagrams/sequence-error.png b/students/Mihnovec_Stas/lab-01/diagrams/sequence-error.png new file mode 100644 index 0000000000000000000000000000000000000000..e911b7fbb9b2445479908414bd526109a6facb81 GIT binary patch literal 38904 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 okpqnVM_1&(J0$SiJ=jk>`@PqEP?Uv>M##UF UI: Нажать "Отправить жалобу" +UI -> CompAPI: POST /api/complaints +activate CompAPI + +CompAPI -> DB: INSERT complaint (status: PENDING) +DB --> CompAPI: complaint_id + +CompAPI -> Moderation: POST /analyze {text} +activate Moderation +Moderation --x CompAPI: TimeoutException (3000ms) +deactivate Moderation + +note over CompAPI: Перехват ошибки.\nПереход в fallback режим. + +CompAPI -> Broker: Publish Event: ModerationRetryQueue {complaint_id} +activate Broker +Broker --> CompAPI: ACK +deactivate Broker + +note over DB: Статус остается PENDING + +CompAPI --> UI: 202 Accepted, "Принято в обработку с задержкой" +deactivate CompAPI + +UI --> User: Показать: "Жалоба сохранена, проверяем..." +@enduml \ No newline at end of file diff --git a/students/Mihnovec_Stas/lab-01/diagrams/sequence-happy.png b/students/Mihnovec_Stas/lab-01/diagrams/sequence-happy.png new file mode 100644 index 0000000000000000000000000000000000000000..f24145eb60063a7537aa5becc73023852efcd62d GIT binary patch literal 43641 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
9D%Fa_*+Nvkg;Pm5wX=j~{y>ql1H$ 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 literal 0 HcmV?d00001 diff --git a/students/Mihnovec_Stas/lab-01/diagrams/sequence-happy.puml b/students/Mihnovec_Stas/lab-01/diagrams/sequence-happy.puml new file mode 100644 index 00000000..55d95e10 --- /dev/null +++ b/students/Mihnovec_Stas/lab-01/diagrams/sequence-happy.puml @@ -0,0 +1,42 @@ +@startuml +skinparam maxMessageSize 150 +actor "Читатель" as User +participant "Web UI" as UI +participant "API Gateway" as API +participant "Complaint Service" as CompAPI +database "PostgreSQL" as DB +participant "AI Moderation" as Moderation +participant "RabbitMQ (Broker)" as Broker + +User -> UI: Нажать "Отправить жалобу" +UI -> API: POST /api/complaints\n{news_id, reason} +activate API + +API -> CompAPI: CreateComplaint() +activate CompAPI + +CompAPI -> DB: Проверка дубликатов (user_id, news_id) +DB --> CompAPI: Not found (OK) + +CompAPI -> DB: INSERT complaint (status: PENDING) +DB --> CompAPI: complaint_id + +CompAPI -> Moderation: POST /analyze {text} +activate Moderation +Moderation --> CompAPI: status: REQUIRES_REVIEW +deactivate Moderation + +CompAPI -> DB: UPDATE status (REVIEW_PENDING) + +CompAPI -> Broker: Publish Event: ComplaintCreated +activate Broker +Broker --> CompAPI: ACK +deactivate Broker + +CompAPI --> API: 201 Created, complaint_id +deactivate CompAPI + +API --> UI: Успешный ответ +deactivate API +UI --> User: Показать уведомление "Жалоба принята" +@enduml \ No newline at end of file diff --git a/students/Mihnovec_Stas/lab-01/scenarios.feature b/students/Mihnovec_Stas/lab-01/scenarios.feature new file mode 100644 index 00000000..83cac695 --- /dev/null +++ b/students/Mihnovec_Stas/lab-01/scenarios.feature @@ -0,0 +1,37 @@ +Feature: Подача жалобы на фейковую новость + + Scenario: Успешная подача жалобы на новость + Given пользователь авторизован как "reader@example.com" + And новость "Инопланетяне приземлились" с ID "NEWS-123" существует + When пользователь отправляет жалобу на "NEWS-123" с причиной "Недостоверный источник" + And сервис авто-модерации работает корректно + Then система создает жалобу со статусом "REVIEW_PENDING" + And система публикует событие "ComplaintCreated" в брокер сообщений + And пользователь видит сообщение "Ваша жалоба отправлена на проверку модераторам" + + Scenario: Ошибка - Новость уже удалена (Not Found) + Given пользователь авторизован как "reader@example.com" + And новость с ID "NEWS-999" была удалена автором минуту назад + When пользователь отправляет жалобу на "NEWS-999" + Then система возвращает ошибку 404 "Новость не найдена" + And жалоба НЕ сохраняется в базу данных + And пользователь видит сообщение "Эта новость уже удалена" + + Scenario: Таймаут сервиса AI-модерации (Fallback) + Given пользователь авторизован как "reader@example.com" + And новость "Секретный заговор" с ID "NEWS-456" существует + When пользователь отправляет жалобу на "NEWS-456" + And сервис авто-модерации не отвечает в течение 3 секунд + Then система сохраняет жалобу со статусом "PENDING" + And система ставит задачу в очередь "ModerationRetryQueue" + And пользователь видит сообщение "Жалоба принята. Из-за высокой нагрузки проверка займет чуть больше времени." + + Scenario: Идемпотентность - Защита от двойного клика (Дубликат) + Given пользователь авторизован как "reader@example.com" + And новость "Шок контент" с ID "NEWS-777" существует + And пользователь уже подавал жалобу на "NEWS-777" 5 минут назад + When пользователь повторно отправляет жалобу на "NEWS-777" + Then система обнаруживает дубликат по ключу "reader@example.com:NEWS-777" + And система НЕ создает новую запись в БД + And система возвращает статус успешного выполнения + And пользователь видит сообщение "Вы уже пожаловались на эту новость ранее" \ No newline at end of file diff --git a/students/Mihnovec_Stas/lab-01/use-case.md b/students/Mihnovec_Stas/lab-01/use-case.md new file mode 100644 index 00000000..0b8632d7 --- /dev/null +++ b/students/Mihnovec_Stas/lab-01/use-case.md @@ -0,0 +1,43 @@ +## Use-case: Подача жалобы на фейковую новость + +**Первичный актор**: Авторизованный читатель + +**Цель**: Сообщить о недостоверной информации в новости для её последующей проверки и возможной блокировки. + +**Предусловия**: +- Пользователь авторизован в системе. +- Статья (новость) существует в системе и доступна для чтения. +- Пользователь ранее не подавал жалобу на эту же новость (проверка идемпотентности). + +**Основной поток** (Happy Path): +1. Пользователь нажимает кнопку "Пожаловаться на фейк" на странице новости. +2. Система запрашивает причину (например, "Недостоверный источник", "Сгенерировано ИИ", "Кликбейт"). +3. Пользователь выбирает причину и нажимает "Отправить". +4. Система (UI) отправляет API-запрос на создание жалобы. +5. Сервис жалоб сохраняет запись в БД со статусом "PENDING". +6. Сервис жалоб синхронно отправляет текст новости во внешний сервис Автомодерации (AI Checker). +7. Сервис Автомодерации возвращает статус "REQUIRES_HUMAN_REVIEW" (требуется ручная проверка). +8. Сервис жалоб обновляет статус жалобы в БД. +9. Система ставит задачу в очередь на асинхронную отправку email-уведомления модераторам. +10. Система возвращает пользователю сообщение об успешной отправке жалобы. + +**Постусловия**: +- Жалоба зафиксирована в БД. +- Новость получает пометку (внутреннюю) о наличии активной жалобы. +- Модераторы уведомлены. + +**Альтернативные потоки**: +- 7a. Сервис Автомодерации уверенно определяет 100% фейк (возвращает "FAKE_CONFIRMED"). + - 7a1. Сервис жалоб автоматически скрывает новость из Ленты. + - 7a2. Автору новости отправляется предупреждение. + - 7a3. Возврат к шагу 10. + +**Исключительные ситуации**: +- 6a. Сервис Автомодерации недоступен (Timeout). + - 6a1. Система ловит ошибку таймаута. + - 6a2. Жалоба остается в БД со статусом "PENDING". + - 6a3. Задача на проверку ставится в брокер сообщений (асинхронный retry). + - 6a4. Пользователь получает ответ: "Жалоба принята и ожидает проверки". +- 4a. Пользователь отправляет повторную жалобу на ту же новость (Double click). + - 4a1. Срабатывает проверка ключа идемпотентности (user_id + news_id). + - 4a2. Система возвращает статус 200 OK и ID уже существующей жалобы без дублирования в БД. \ No newline at end of file diff --git "a/students/Mihnovec_Stas/lab-01/\320\236\321\202\321\207\320\265\321\202.md" "b/students/Mihnovec_Stas/lab-01/\320\236\321\202\321\207\320\265\321\202.md" new file mode 100644 index 00000000..79815261 --- /dev/null +++ "b/students/Mihnovec_Stas/lab-01/\320\236\321\202\321\207\320\265\321\202.md" @@ -0,0 +1,231 @@ +

Министерство образования Республики Беларусь

+

Учреждение образования

+

"Брестский Государственный технический университет"

+

Кафедра ИИТ

+





+

Лабораторная работа №1

+

По дисциплине: "Проектирование интернет-систем"

+

Тема: "Сценарий транзакции: моделирование use-case и границ ответственности"

+





+

Выполнил:

+

Студент 3 курса

+

Группы ПО-12

+

Михновец С. Э.

+

Проверил:

+

Несюк А.Н.

+




+

Брест 2026

+ +--- + +## Цель работы + +Научиться анализировать бизнес-процессы интернет-системы, выявлять границы ответственности компонентов и моделировать транзакционные сценарии с учётом возможных сбоев. + +--- + +## Вариант №37 - Новости «Без фейков» 📰 + +**Питч:** Читаем умно, делимся быстро. + +**Ядро домена:** Источники, Лента, Теги, Избранное, Жалобы. + +--- + +## Ход выполнения работы + +### 1. Структура проекта + +```text +lab-01/ +├── Отчет.md # Основной отчёт (этот документ) +├── use-case.md # Текстовое описание use-case +├── diagrams/ +│ ├── sequence-happy.puml # PlantUML для успешного сценария +│ ├── sequence-happy.png # Экспорт диаграммы +│ ├── sequence-error.puml # PlantUML для сценария с ошибкой +│ └── sequence-error.png # Экспорт диаграммы +├── scenarios.feature # Gherkin-сценарии +└── analysis.md # Анализ границ ответственности +``` + +--- + +### 2. Use-case описание + +👉 **Ссылка на файл:** [use-case.md](use-case.md) + +**Основной сценарий:** Подача жалобы на фейковую новость с автоматической проверкой + +**Первичный актор:** Авторизованный читатель + +**Цель:** Сообщить о недостоверной информации в новости для её последующей проверки и возможной блокировки. + +**Краткое описание основного потока:** +1. Пользователь нажимает "Пожаловаться на фейк" и выбирает причину. +2. Система отправляет API-запрос на создание жалобы. +3. Сервис сохраняет жалобу в БД со статусом "PENDING". +4. Система синхронно запрашивает внешний сервис AI-модерации для анализа текста. +5. AI-модерация возвращает статус "REQUIRES_HUMAN_REVIEW". +6. Статус жалобы в БД обновляется. +7. В очередь ставится задача на отправку уведомления модераторам. + +**Альтернативные потоки:** +- AI-модерация на 100% уверена, что это фейк -> Автоматическое скрытие новости из ленты. + +**Исключительные ситуации:** +- Таймаут сервиса AI-модерации (переход в асинхронный режим). +- Пользователь отправляет повторную жалобу на ту же новость (защита от дубликатов). +- Новость была удалена до момента отправки жалобы (404 Not Found). + +--- + +### 3. Диаграммы последовательности (Sequence Diagrams) + +#### 3.1. Happy Path (успешный сценарий) + +👉 **PlantUML исходник:** [sequence-happy.puml](diagrams/sequence-happy.puml) + +![Диаграмма успешного сценария](diagrams/sequence-happy.png) + +**Описание потока:** +- Пользователь отправляет жалобу. `Complaint Service` проверяет БД на дубликаты и сохраняет запись. Затем синхронно вызывается внешний сервис `AI Moderation`. После получения ответа статус обновляется, и публикуется событие в `RabbitMQ` для асинхронного уведомления модераторов. + +**Участники:** +- Читатель (User) +- Web UI / API Gateway +- Complaint Service (Сервис жалоб) +- PostgreSQL (База данных) +- AI Moderation (Внешний сервис проверки ИИ) +- RabbitMQ (Брокер сообщений) + +#### 3.2. Error Case (сценарий с ошибкой) + +👉 **PlantUML исходник:** [sequence-error.puml](diagrams/sequence-error.puml) + +![Диаграмма сценария с ошибкой](diagrams/sequence-error.png) + +**Описание потока:** +- Во время вызова `AI Moderation` происходит таймаут (сервис недоступен или перегружен). `Complaint Service` перехватывает исключение. Вместо того чтобы выдавать ошибку пользователю, жалоба остается в БД в статусе `PENDING`, а задача на проверку отправляется в очередь `RabbitMQ` (Fallback). Пользователь получает статус 202 Accepted. + +--- + +### 4. Gherkin-сценарии + +👉 **Ссылка на файл:** [scenarios.feature](scenarios.feature) + +**Реализовано сценариев:** 4 + +**Список сценариев:** +1. ✅ **Успешный сценарий:** Успешная подача жалобы на новость. +2. ✅ **Ошибка:** Новость уже удалена (Not Found). +3. ✅ **Ошибка:** Таймаут сервиса AI-модерации (Fallback в асинхронный режим). +4. ✅ **Ошибка:** Идемпотентность - Защита от двойного клика (Дубликат). + +**Пример сценария (Успешный путь):** +```gherkin +Feature: Подача жалобы на фейковую новость + +Scenario: Успешная подача жалобы на новость + Given пользователь авторизован как "reader@example.com" + And новость "Инопланетяне приземлились" с ID "NEWS-123" существует + When пользователь отправляет жалобу на "NEWS-123" с причиной "Недостоверный источник" + And сервис авто-модерации работает корректно + Then система создает жалобу со статусом "REVIEW_PENDING" + And система публикует событие "ComplaintCreated" в брокер сообщений + And пользователь видит сообщение "Ваша жалоба отправлена на проверку модераторам" +``` + +--- + +### 5. Анализ границ ответственности + +👉 **Ссылка на файл:** [analysis.md](analysis.md) + +#### 5.1. Транзакционные границы + +| Операция | Синхронная/Асинхронная | Откат при ошибке | Retry-стратегия | Идемпотентность | +|----------|------------------------|------------------|-----------------|-----------------| +| Сохранение жалобы в БД | Синхронная | Да (ROLLBACK) | Нет (контролируется UI) | Да (составной ключ user_id + news_id) | +| Проверка через AI Moderation | Синхронная | Нет (Переход в Async) | Отправка в очередь RabbitMQ с задержкой | Да (Сервис ИИ кэширует хеш текста) | +| Уведомление модераторов (Email)| Асинхронная | Нет (best-effort) | 3 попытки (через брокер сообщений) | Да (дедупликация по complaint_id) | + +#### 5.2. Обработка исключительных ситуаций + +**Реализовано стратегий обработки:** 2 + +##### Исключительная ситуация 1: Таймаут сервиса Автомодерации + +- **Условие возникновения:** HTTP POST запрос к внешнему сервису ИИ не отвечает более 3 секунд. +- **Обнаружение:** HTTP-клиент (например, Axios) выбрасывает `TimeoutException`. +- **Реакция:** Система ловит ошибку, не откатывает БД. Публикует событие `ModerationRetryQueue` в RabbitMQ для фоновой обработки. +- **Компенсация:** Не требуется откат. Жалоба остается в статусе "PENDING" до успешной асинхронной обработки воркером. +- **Уведомление пользователя:** "Жалоба принята. Из-за высокой нагрузки проверка займет чуть больше времени." (HTTP 202 Accepted). + +##### Исключительная ситуация 2: Нарушение уникальности (Double click) + +- **Условие возникновения:** Пользователь дважды нажал кнопку "Отправить", сгенерировав два параллельных запроса. +- **Обнаружение:** База данных PostgreSQL выбрасывает `UniqueConstraintViolationException` на составной индекс `(user_id, news_id)`. +- **Реакция:** Транзакция второго запроса прерывается. Система перехватывает ошибку БД. +- **Компенсация:** Откат (ROLLBACK) транзакции второго (дублирующего) запроса. +- **Уведомление пользователя:** Возвращается успешный ответ (HTTP 200) с сообщением: "Вы уже пожаловались на эту новость ранее." + +--- + +## Таблица критериев оценки + +| Критерий | Баллы | Выполнено | +|----------|-------|-----------| +| Use-case описание (полнота: акторы, предусловия, основной поток, альтернативы, исключения) | 15 | ✅ | +| Sequence diagram (happy path) - корректность нотации UML, включение всех ключевых компонентов | 20 | ✅ | +| Sequence diagram (error case) - моделирование хотя бы одной исключительной ситуации | 15 | ✅ | +| Gherkin-сценарии - минимум 4 сценария (1 успешный + 3 ошибочных) | 20 | ✅ | +| Анализ границ ответственности - таблица транзакционных границ, обоснование выбора синхронных/асинхронных операций | 15 | ✅ | +| Обработка исключений - описание стратегий retry, компенсации, уведомлений | 10 | ✅ | +| Качество документации - оформление, читаемость, грамотность | 5 | ✅ | +| **ИТОГО** | **100** | | + +--- + +## Контрольные вопросы + +**Подготовка к защите:** + +1. **Что такое транзакционная граница? Где она проходит в вашем сценарии?** + - Транзакционная граница — это область системы, в пределах которой набор операций выполняется атомарно (все или ничего). В моем сценарии граница проходит на уровне базы данных Complaint Service: проверка дубликатов и сохранение жалобы со статусом `PENDING` выполняются в одной транзакции. Вызов внешнего сервиса AI вынесен за эту границу, чтобы долгий ответ сети не блокировал подключение к БД. + +2. **Почему операция X выбрана синхронной, а Y - асинхронной?** + - **Синхронная (Запись в БД):** Система должна гарантированно сохранить данные жалобы и вернуть пользователю ответ с ID операции, чтобы он понимал, что запрос не потерян. + - **Асинхронная (Уведомление модераторов):** Отправка Email может занимать время. Пользователю не нужно ждать на сайте, пока письмо дойдет до модератора. Это можно сделать в фоне. + +3. **Как обеспечить идемпотентность при повторных запросах?** + - Идемпотентность обеспечивается созданием составного уникального индекса в базе данных по полям `user_id` и `news_id`. Если один и тот же пользователь попытается отправить жалобу на одну и ту же новость дважды, БД выбросит ошибку уникальности, которую сервис перехватит и вернет информацию о уже существующей жалобе без создания дубликата. + +4. **Что произойдёт, если внешний сервис вернёт ошибку после частичного выполнения операции?** + - Если сервис AI-модерации упадет после того, как жалоба была записана в БД, система не будет делать откат (rollback) жалобы. Вместо этого сработает паттерн Fallback: жалоба будет помещена в очередь брокера сообщений (RabbitMQ) для повторной попытки (Retry) проверки в фоновом режиме, когда внешний сервис снова станет доступен. + +5. **Как система обнаружит, что внешний сервис недоступен?** + - Через `TimeoutException` (если сервис не ответил за заданное время, например 3 секунды) или при получении HTTP-статусов ошибок из серии `5xx` (Internal Server Error, Bad Gateway). Также может использоваться паттерн Circuit Breaker для мониторинга процента отказов. + +6. **Какие данные нужно логировать для диагностики сбоев?** + - Нужно логировать: `timestamp` (время сбоя), `user_id`, `news_id`, `complaint_id`, текст ошибки (`Exception message` и `Stack Trace`), HTTP-статус ответа от внешнего сервиса, а также время выполнения запроса до падения (duration), чтобы диагностировать проблемы с производительностью сети. + +--- + +## Ссылка на репозиторий + +👉 **GitHub:** [[Cсылку на репозиторий]](https://github.com/dizmorall/PIS-2026) + +--- + +## Вывод + +✍️ В ходе выполнения лабораторной работы был проанализирован бизнес-процесс платформы "Новости «Без фейков»" на примере сценария модерации контента. Были разработаны текстовые use-case описания и визуальные модели взаимодействия компонентов с использованием инструмента PlantUML. Сформированы Gherkin-сценарии для автоматизированного BDD-тестирования, покрывающие как успешный путь, так и нештатные ситуации. Были определены границы транзакций: выделена критическая секция (запись в БД) и вынесены за её пределы нестабильные внешние вызовы (AI-проверка). Освоены паттерны обеспечения отказоустойчивости интернет-систем, такие как асинхронный Fallback через очереди сообщений и обеспечение идемпотентности API. + +--- + +**Дата выполнения:** 05.03.2026 + +**Оценка:** _____________ + +**Подпись преподавателя:** _____________ diff --git a/students/students.csv b/students/students.csv index 2e7c4e24..d34a08e8 100644 --- a/students/students.csv +++ b/students/students.csv @@ -1 +1,2 @@ Вариант,Group,№,sub,Name,NameLatin,Directory,Github Username,#1,#2,#3,#4,#5,#6,#7,#8,#9,Rating +37,ПО-12,15,2,Михновец Станислав Эдуардович,Mihnovec Stas,Mihnovec_Stas,dizmorall,,,,,,,,,, \ No newline at end of file diff --git a/tasks/01_transaction_scenario/examples/diagrams/sequence-happy.puml b/tasks/01_transaction_scenario/examples/diagrams/sequence-happy.puml index f9eb1287..3a9cae7b 100644 --- a/tasks/01_transaction_scenario/examples/diagrams/sequence-happy.puml +++ b/tasks/01_transaction_scenario/examples/diagrams/sequence-happy.puml @@ -1,4 +1,4 @@ -@startuml +@startuml happy title Успешный сценарий: Создание заявки и формирование группы actor "Координатор" as Coord