GetAnalyst - Навыки • Системный анализ • Бизнес-анализ
Разбор задач на проектирование систем 🚀 Канал для системных аналитиков, бизнес-аналитиков, тестировщиков и менеджеров проектов Админ @getanalyst Сайт https://getanalyst.ru Чат t.me/getanalystchat Начинающим в IT @getanalyststart
Больше📈 Аналитический обзор Telegram-канала GetAnalyst - Навыки • Системный анализ • Бизнес-анализ
Канал GetAnalyst - Навыки • Системный анализ • Бизнес-анализ (@getanalysts) языкового сегмента Русский является активным участником. Сейчас сообщество объединяет 22 669 подписчиков, занимая 5 839 место в категории Технологии и приложения и 28 992 место в регионе Россия.
📊 Показатели аудитории и динамика
С момента создания невідомо проект демонстрирует стремительный рост, собрав аудиторию из 22 669 подписчиков.
Согласно последним данным от 26 октября, 2026, канал показывает стабильную активность. За последние 30 дней изменение числа участников составило 151, а за последние 24 часа — 13, при этом общий охват остаётся высоким.
- Статус верификации: Не верифицирован
- Уровень вовлечённости (ER): Средний показатель вовлечённости аудитории составляет 13.26%. В первые 24 часа после публикации контент обычно набирает 7.76% реакций от общего числа подписчиков.
- Охват публикаций: В среднем каждый пост получает 3 005 просмотров. В течение первых суток публикация набирает 1 758 просмотров.
- Реакции и взаимодействия: Аудитория активно поддерживает контент: среднее количество реакций на один пост — 38.
- Тематические интересы: Контент сосредоточен на ключевых темах, таких как api, брокер, архитектура, oauth, микросервисов.
📝 Описание и контентная политика
Автор описывает ресурс как площадку для выражения субъективного мнения:
“Разбор задач на проектирование систем 🚀 Канал для системных аналитиков, бизнес-аналитиков, тестировщиков и менеджеров проектов
Админ @getanalyst
Сайт https://getanalyst.ru
Чат t.me/getanalystchat
Начинающим в IT @getanalyststart”
Благодаря высокой частоте обновлений (последние данные получены 27 октября, 2026) канал поддерживает актуальность и высокий уровень охвата публикаций. Аналитика показывает, что аудитория активно взаимодействует с контентом, что делает его важной точкой влияния в категории Технологии и приложения.
Ну какого черта?! Я сапожник без сапог!!! Для клиентов я с удовольствием исследую процессы и настраиваю им автоматизацию и агентов. Мне за это платят 🤑 А когда дело доходит до собственной рутины, включается классическое: «Сейчас быстрее сделаю вручную, а агента настрою потом».И это «потом» может длиться месяцами 🙌 👉 Поэтому теперь у меня новое правило: если задача повторяется хотя бы раз в месяц, я не просто снова её выполняю, а сначала думаю, можно ли делегировать её AI-агенту. В итоге последние пару недель, вместо того чтобы выполнить задачку на 4 часа, я тратила все 8-12: 1. разбираю процесс по шагам 2. собираю AI-агента и подключаю инструменты 3. тестирую, нахожу ошибки и переделываю И нет, сразу времени больше не становится. Наоборот, сначала работы становится ещё больше. Зато! Задачи, которые в мае я вообще не могла доверить AI, сейчас агенты выполняют вполне уверенно. ‼️ И у меня нет возможности отложить текущие задачи и снять себя нагрузку, чтобы делать AI-агентов. Я трачу на это личное время. Минус сон, минус зал, минус отдых 🤬😡😭 Мой фитнес-браслет весь красно-жёлтый по восстановлению (это плохо), а недостаток сна приходится восполнять в выходные. Нет, это не та часть эксперимента, которую я рекомендую повторять. Но блин. Бесит. Иначе не получалось. Итого, делаю главные выводы: ▫️ Самое сложное — не выбрать модель, написать промпт или разобраться в агентах. ▫️ Самое сложное — нормально понять и описать собственный процесс, и найти на это время+вдохновение. Для меня таким мотивационным пинком стала учёба в Университете Джонса Хопкинса 💙 Сейчас создавать агентов можно разными способами: программировать, собирать в конструкторах или настраивать прямо внутри ChatGPT или Claude. Возможностей море. Мой следующий этап - создать CEO-агента: руководителя, который будет контролировать работу остальных агентов 😈 Но сначала нужно закончить этот сумасшедший месяц, в который я решила делегировать максимум возможного. На этом пост нытья окончен. Оставайтесь, через месяц расскажу, окупились ли вложения времени и денег в эту виртуальную команду — и начала ли я наконец работать меньше 🥲😀 📱 Tg | 💙 ВК | 💬 Max
ИИ не заменит аналитика, который умеет думать. Но аналитик с ИИ будет востребованнее того, кто продолжает всё делать вручную 🚀Присоединяйтесь на следующей неделе! 📱 Tg | 💙 ВК | 💬 Max
GET /documents/4831
Ответ:
HTTP/1.1 200 OK
ETag: "17"
Content-Type: application/json
{
"name": "Версия 0",
"number": "123/9364",
"text": "Тут текст ...."
}
Оба пользователя редактируют документ, соответствующий версии ETag: "17".
🏁 Первый пользователь сохраняет изменения
Приложение передаёт полученный ETag в заголовке If-Match, в метод изменения документа.
Запрос:
PATCH /documents/4831
If-Match: "17"
Content-Type: application/json
{
"name": "Версия от Пети",
"number": "123/9364",
"text": "Тут текст ...."
}
Сервер при получении API запроса:
1️⃣ проверяет в API, что текущий ETag=17
2️⃣ проверяет в БД, что ETag совпадает с текущей версией документа
3️⃣ сервер сохраняет изменения в БД
4️⃣ возвращает успешный ответ на запрос с новым ETag:
HTTP/1.1 204 No Content
ETag: "18"
и телом ответа, при необходимости.
🏁 Второй пользователь пытается сохранить документ, но уже старую версию
Его запрос такой же как и у первого клиента, ETag всё ещё 17, хотя по факту изменение первого пользователя уже принято и изменения произошли.
Запрос:
PATCH /documents/4831
If-Match: "17"
Content-Type: application/json
{
"name": "Версия от Насти",
"number": "123/9364",
"text": "Тут текст ...."
}
Но документ уже имеет ETag: "18" после изменений первого пользователя (Пети).
Сервер не должен перезаписывать изменения первого пользователя.
Сервер при получении API запроса:
1️⃣ проверяет в API, что текущий ETag=17
2️⃣ проверяет по БД текущую версию, а там уже 18
3️⃣ возвращает ошибку:
HTTP/1.1 412 Precondition Failed
Content-Type: application/json
{
"errorCode": "VERSION_CONFLICT",
"message": "Документ был изменён другим пользователем. Обновите данные и повторите действие.",
"traceId": "2a48c7..."
}
Клиенту для обработки такой ошибки надо:
1. повторно получить новую версию документа GET /documents/4831
2. предложить пользователю сравнить версии: объединить изменения или начать редактирование заново
❗️ Нельзя получить новую версию данных с ETag=18 и автоматически повторить запрос на изменение с новым ETag: так клиент всё равно может затереть чужие данные.
📌 Логика обработки запроса на редактирование
✅ If-Match совпадает с текущим ETag
→ выполнить изменение и вернуть новый ETag
❌ If-Match не совпадает
→ вернуть 412 Precondition Failed и не изменять ресурс
⚠️ If-Match отсутствует, хотя условное обновление обязательно
→ можно вернуть 428 Precondition Required, если это предусмотрено контрактом API
Само значение ETag непрозрачно для клиента: его не нужно разбирать или вычислять самостоятельно. Клиент должен сохранить полученное значение от GET /resources/{id} и вернуть его в If-Match для PATCH /resources/{id} без изменений.
📌 Почему здесь HTTP-412, а не HTTP-409?
412 Precondition Failed означает, что не выполнилось условие из заголовка If-Match.
409 Conflict используют для других конфликтов состояния или бизнес-правил, не связанных с проверкой условного запроса.
📌 Где хранится ETag в БД?
Сам ETag обычно не хранится в БД в виде строки ETag: "18".
В таблице ресурса хранится техническое поле версии:
таблица document
———
id: 4831
name: Версия 0
version: 17
updated_at: ...
———
К посту добавила более подробный чек-лист для вашей копилки полезных материалов от GetAnalyst 🤝
#RestApiGARange
Но это не одно и то же.
📌 Потоковая передача файла
При обычной потоковой передаче клиент отправляет запрос на получение файла:
GET /files/4831/content
Сервер проверяет права пользователя, начинает читать файл из хранилища и сразу передаёт полученные байты клиенту.
Ему не нужно сначала загружать весь файл в оперативную память и только потом формировать ответ.
HTTP/1.1 200 OK
Content-Type: application/pdf
Content-Disposition: attachment; filename="report.pdf"
Content-Length: 5242880
%PDF-1.7...
Для клиента это один обычный HTTP-ответ со всем содержимым файла.
Потоковая передача описывает то, как сервер читает и отправляет данные. Это не отдельный формат ответа и не означает, что файл обязательно можно скачать частями.
👉 Во время потоковой передачи HTTP-ответ остаётся незавершённым, а соединение с клиентом — активным, пока сервер не передаст весь файл или передача не прервётся.
📌 Получение файла частями с помощью Range
Если клиенту нужно получить только определённую часть файла, он передаёт заголовок Range:
GET /files/4831/content
Range: bytes=0-1048575
Такой запрос означает:
💡 вернуть байты с позиции 0 по позицию 1048575.
Сервер возвращает не весь файл, а только запрошенный диапазон:
HTTP/1.1 206 Partial Content
Content-Type: application/pdf
Content-Disposition: attachment; filename="report.pdf"
Accept-Ranges: bytes
Content-Range: bytes 0-1048575/5242880
Content-Length: 1048576
Обратите внимание на headers:
▫️ 206 Partial Content — возвращена только часть файла
▫️ Accept-Ranges: bytes — сервер поддерживает получение файла по диапазонам байтов
▫️ Content-Range — показывает границы возвращённой части и полный размер файла
▫️ Content-Length — содержит размер возвращаемой части, а не всего файла
Поддержка Range нужна, например, для:
▫️ возобновления прерванного скачивания
▫️ перемотки видео и аудио
▫️ параллельной загрузки частей большого файла
▫️ получения только необходимого фрагмента данных
👉 Что вернуть при некорректном диапазоне
Если клиент запросил диапазон, которого в файле не существует, сервер возвращает:
HTTP/1.1 416 Range Not Satisfiable
Content-Range: bytes */5242880
Число после / показывает полный размер файла.
Например, нельзя запросить байты начиная с позиции 6000000, если размер файла составляет только 5242880 байт.
👉 Какие заголовки надо определить в требованиях
Content-Type — формат содержимого файла:
Content-Type: application/pdf
Content-Disposition — как браузер должен обработать файл:
Content-Disposition: attachment; filename="report.pdf"
attachment предлагает скачать файл.
Если файл должен открываться в браузере, можно использовать:
Content-Disposition: inline; filename="report.pdf"
Content-Length — размер всего ответа в байтах:
Content-Length: 5242880
В ответе 206 Partial Content это размер возвращаемой части файла.
Accept-Ranges — сообщает о поддержке получения файла частями:
Accept-Ranges: bytes
Content-Range — показывает, какой диапазон возвращён:
Content-Range: bytes 0-1048575/5242880
👉 Как описать в задаче
Можно использовать такую формулировку:
Метод GET /files/{fileId}/content должен проверить наличие файла и права пользователя на его получение.
Если заголовок Range не передан, метод возвращает всё содержимое файла с кодом 200 OK. Сервер должен читать файл из хранилища и передавать его клиенту потоком, не загружая файл целиком в оперативную память.
Если передан корректный заголовок Range, метод возвращает запрошенный диапазон байтов с кодом 206 Partial Content.
Если запрошенный диапазон не существует, метод возвращает 416 Range Not Satisfiable.
🔗 Пример Amazon S3 GetObject
Используйте этот пост как основу для постановки задач на получение больших файлов через REST API 🩵
#RestApiGA | Tg | ВК | Max
HTTP/1.1 200 OK
Content-Type: application/pdf
Content-Disposition: attachment; filename="report.pdf"
%PDF-1.7...
Если файл большой, сервер может читать его из хранилища и сразу передавать клиенту частями, не загружая целиком в оперативную память - это уже будет потоковая передача.
🔗 Пример Google Drive
📌 2. Файл закодированный в Base64
Здесь сервер сначала преобразует байты PDF-файла в строку Base64, а потом помещает её в JSON.
HTTP/1.1 200 OK
Content-Type: application/json
{
"fileName": "report.pdf",
"contentType": "application/pdf",
"content": "JVBERi0xLjcKJ..."
}
Клиент должен:
▫️ получить JSON
▫️ извлечь значение поля content
▫️ декодировать Base64 обратно в байты
▫️ сохранить полученные байты в файл нужного формата
🔺 Base64 без необходимости лучше не использовать: объём данных увеличится примерно на треть, а серверу и клиенту потребуется больше памяти на обработку.
🔗 Пример GitHub
📌 3. Вернуть временную ссылку
Подходит для больших файлов и файлов из объектного хранилища — например, S3.
API проверяет права пользователя и возвращает ссылку, по которой клиент скачивает файл напрямую из хранилища:
{
"downloadUrl": "https://storage.example.com/...",
"expiresAt": "2026-10-20T12:00:00Z"
}
В требованиях нужно указать:
▫️ срок действия ссылки
▫️ для какого файла и HTTP-метода она действует
▫️ можно ли использовать её повторно
▫️ нужно ли журналировать факт выдачи ссылки, не сохраняя сам URL
🔗 Пример для Dropbox
📌 4. Разделить метаданные и содержимое файла
Подходит, если сначала нужно показать пользователю информацию о файле, а скачивание он запускает отдельно.
Сочетается с любым из трёх способов выше.
GET /files/{fileId}
Метод возвращает метаданные:
{
"id": "4831",
"name": "report.pdf",
"mediaType": "application/pdf",
"size": 5242880,
"status": "READY"
}
Сам файл возвращает отдельный метод:
GET /files/{fileId}/content
Примеры Box API:
🔗 получение информации о файле (тут и URL на скачивание)
🔗 скачивание содержимого файла.
📌 5. Получение файла частями
Подходит для больших файлов, видео, возобновления прерванной загрузки и параллельного скачивания.
Клиент передаёт диапазон байтов:
GET /files/4831/content
Range: bytes=0-1048575
Сервер возвращает только запрошенную часть:
HTTP/1.1 206 Partial Content
Content-Type: application/pdf
Accept-Ranges: bytes
Content-Range: bytes 0-1048575/5242880
Content-Length: 1048576
🔗 Пример Amazon S3 GetObject
Важно: потоковая передача и Range — не одно и то же.
При потоковой передаче сервер последовательно читает и отправляет файл, не загружая его целиком в память. Клиент при этом может получить обычный ответ 200 OK.
При использовании Range клиент сам запрашивает конкретную часть файла, а сервер возвращает 206 Partial Content.
Сохраняйте пост и используйте его как шпаргалку, когда будете описывать получение файлов в REST API 🤝
#RestApiGA | Tg | ВК | Max
SELECT
c.full_name,
COUNT(DISTINCT o.id) AS orders_count,
SUM(oi.quantity) AS items_count,
COUNT(DISTINCT p.category_id) AS categories_count,
SUM(oi.quantity * oi.unit_price) AS total_spent
FROM customer c
JOIN "order" o ON o.customer_id = c.id
JOIN order_item oi ON oi.order_id = o.id
JOIN product p ON p.id = oi.product_id
WHERE o.status = 'PAID'
AND o.created_at >= DATE '2026-01-01'
AND o.created_at < DATE '2027-01-01'
GROUP BY c.id, c.full_name
HAVING COUNT(DISTINCT o.id) >= 3
AND COUNT(DISTINCT p.category_id) >= 2
AND SUM(oi.quantity * oi.unit_price) > 20000
ORDER BY total_spent DESC;
Главный подвох — COUNT(DISTINCT o.id): после соединения с товарами один заказ превращается в несколько строк.
#БД_и_SQL_GAGET /products?city=spb&priceFrom=1000&priceTo=5000&sort=rating...
Логика правильная:
+ GET - про получение данных.
+ мы ничего не создаём, ничего не меняем, просто читаем данные.
Но у GET есть проблема.
Если фильтров много:
▫️ URL становится огромным
▫️ прокси, браузеры и балансировщики могут резать длинные адреса
▫️ сложные JSON-фильтры неудобно кодировать в строку
▫️ параметры запроса засоряют логи
Для простого поиска GET подходит.
Для сложного поиска — уже нет.
Пример GET
❌ POST с фильтрами в теле запроса.
Можно красиво передать фильтр в JSON:
POST /products/search
{
"city": "spb",
"priceFrom": 1000,
"priceTo": 5000,
"categories": ["hotel", "apartment"],
"sort": "rating,asc"
}
Но появляются другие проблемы:
▫️ нецелевое использование: POST - предназначен для создания данных, а не для чтения
▫️ он не идемпотентный: при повторном вызове ожидаются изменения
▫️ его сложнее кэшировать
Пример POST
Новый ответ:
✅ QUERY с фильтрами в теле запроса
Он забирает лучшее у двух подходов:
🟢 От POST он берёт тело запроса
То есть сложный фильтр можно передать в JSON:
QUERY /products/search
Content-Type: application/json
{
"city": "spb",
"priceFrom": 1000,
"priceTo": 5000,
"categories": ["hotel", "apartment"],
"sort": "rating, asc"
}
🟢 А по смыслу QUERY ближе к GET
Он говорит серверу и всей инфраструктуре по пути: этот запрос только читает данные и не меняет состояние ресурса.
Из этого следуют два важных свойства:
👍 1. QUERY можно безопасно повторять
Если сеть оборвалась, клиент может повторить запрос.
Метод заявлен как идемпотентный.
👍 2. Ответ на QUERY можно кэшировать
Но не просто по URL.
Ключ кэша должен учитывать:
▫️ адрес запроса
▫️ тело запроса
▫️ связанные метаданные
То есть:
один и тот же URL + один и тот же фильтр = можно вернуть готовый ответ из кэша.
А другой фильтр в body = другой результат и другой ключ кэша.
Это особенно полезно для тяжёлых поисковых запросов, каталогов и аналитических выборок.
❗️ Актуальные проблемы 2026 для HTTP QUERY
Хотя QUERY уже есть в стандарте HTTP, экосистема ещё догоняет.
Проблемы:
▫️ сервер или фреймворк пока не понимает такой метод
▫️ API Gateway может не пропустить незнакомый тип запроса
▫️ CDN может ещё не уметь нормально кэшировать такие ответы
▫️ генераторы документации не знают этот метод (в том числе OPEN API)
▫️ в Postman и других инструментах тестирования QUERY пока не добавлен
▫️ SDK не поддерживают этот метод
▫️ в браузере могут появиться дополнительные проверки перед запросом
Поэтому пока с внедрением QUERY лучше не торопиться.
👉 Как внедрять:
▫️ для внутренних API (обмен данными между микросервисами, для ваших веб- и мобильных приложений) — можно начинать использовать.
▫️ для публичных API (подключение к вам партнеров, интеграции с внешними систами) — лучше пока подождать.
Перед внедрением обязательно проверьте поддержку в стеке разработки, документации, клиентах, шлюзах, кэшах и инструментах мониторинга.
Так что теперь в HTTP:
👉 GET, POST, PUT, PATCH, DELETE, QUERY
OPTIONS, HEAD, TRACE, CONNECT
👉 Запомните логику:
▫️ простой поиск — GET
▫️ создание — POST
▫️ сложный поиск с body — QUERY
Стандарт появился.
Теперь ждём, когда инструменты и инфраструктура массово обновятся.
❤️🔥 Подписывайтесь на GetAnalyst, чтобы быть в курсе актуальных обновлений IT, важных для аналитиков
#ИнтеграцииGA #RestApiGA