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