TGViewer
Всё о разработке | Леонид Ченский Всё о разработке | Леонид Ченский @leoscode · 731 subscribers
Post #159 964
⚠️ Когда API молчит - страдает клиент

Представьте, у вас есть метод:
rpc GetUsers(GetUsersRequest) returns (GetUsersResponse);

message GetUsersRequest {
repeated string ids = 1;
optional string city = 2;
int32 page = 3;
int32 page_size = 4;
}


Вы вызываете GetUsers с 200 идентификаторами, ожидаете получить всех.
А сервер молча возвращает 100.
Без ошибки и без всякого предупреждения.

Почему? Да потому что в коде спрятан жёсткий limit = 100, о котором никто не знал.

Такие вещи ломают доверие к API.
Когда контракт неявный, клиенту остаётся только гадать: это баг, фильтр, лимит, пагинация или оптимизация?

А ещё хуже, когда такое поведение всплывает на production, и выясняется, что система теряла данные неделями (классика жанра).

💡 Хорошее API — прозрачное API.

— если есть лимиты, они должны быть явно задокументированы или возвращаться в ответе;
Часто вижу, что разработчики в gRPC не оставляют никаких комментариев в .proto - поверьте, просто спецификации НЕДОСТАТОЧНО. Клиент должен понимать не только что вызвать, но и чего ожидать.

— если что-то отфильтровано, клиент должен понимать, почему;
даже простая метка filtered=true , partial=true или список missing_ids уже делает API дружелюбнее.

— если есть пагинация, требуйте её явно от всех потребителей;
не стоит выдавать неполный ответ и надеяться, что клиент догадается, сколько можно запросить за раз.

Хорошо спроектированное и описанное API спасает от множетсво багов и недопониманий в будущем. Проводите ревью API тщательно, господа.

P.S. На мой взгляд хорошее gRPC API описано примерно так:
// Pagination - пагинация
message Pagination {
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = {
json_schema: {
title: "Pagination"
description: "Пагинация"
}
};

// page_number - номер страницы. По умолчанию 1
uint64 page_number = 1 [
json_name = "page_number",
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {default: "1"}
];

// page_size - размер страницы. По умолчанию 50
uint64 page_size = 2 [
json_name = "page_size",
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {default: "50"}
];
}

// PageInfo - информация о странице
message PageInfo {
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = {
json_schema: {
title: "PageInfo"
description: "Информация о странице"
}
};

// total_count - общее кол-во записей
uint64 total_count = 1 [json_name = "total_count"];

// count - кол-во полученных записей на текущей странице
uint64 count = 2 [json_name = "count"];

// page_number - текущий номер страницы
uint64 page_number = 3 [json_name = "page_number"];

// page_total - общее кол-во страниц
uint64 page_total = 4 [json_name = "page_total"];

// page_size - размер страницы
uint64 page_size = 5 [json_name = "page_size"];
}

А вы как считаете?
  • 👍 14
  • 💯 3
  • 🔥 2
  • 🗿 2
  • 👏 1
More from @leoscode
  1. Sep 15, 2026Помню как в детстве хотел такого же ассистента как Jarvis у Железного человека. Сейчас буд…
  2. Aug 24, 2026Гипотетическая история Представьте завтра все датацентры «вдруг» перестанут работать. Прив…
  3. Aug 4, 2026"Капризный день"
  4. Jul 17, 2026Пользуюсь случаем, напишу тут: ищу заряжененного Go разработчика к себе в команду. Ссылка…
  5. Jul 14, 2026Утро вторника началось не с кофе… Кто положил, признавайтесь!)
  6. Jul 1, 2026Согласны? 👍 Да 🗿Нет
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →