Представьте, у вас есть метод:
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"];
}
А вы как считаете?