fix(iot): пагинация — tiebreaker ts DESC,id DESC + потолок limit; точный лог (Этап 5)
- QueryTelemetry: ORDER BY ts DESC, id DESC (был без tiebreaker → нестабильная пагинация при одинаковых ts). - ListIoTDevices: limit дефолт 100, потолок 1000 (ошибка парсинга больше не даёт безлимитный запрос). - Логи 'batch dropped' → 'валидные строки — построчно' (после fallback батч НЕ теряется целиком).
This commit is contained in:
@@ -221,15 +221,27 @@ func (h *Handler) CreateIoTDevice(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// ListIoTDevices — GET /v1/namespaces/{ns}/iot/devices (без паролей).
|
||||
// Пагинация: ?limit=N&offset=M (0 = без ограничения).
|
||||
// Пагинация: ?limit=N&offset=M. limit — дефолт 100, потолок 1000 (защита от
|
||||
// безлимитного запроса при ошибке парсинга).
|
||||
func (h *Handler) ListIoTDevices(w http.ResponseWriter, r *http.Request) {
|
||||
ns := pathVar(r, "namespace")
|
||||
if ns == "" {
|
||||
ns = "default"
|
||||
}
|
||||
|
||||
limit, _ := strconv.Atoi(r.URL.Query().Get("limit"))
|
||||
offset, _ := strconv.Atoi(r.URL.Query().Get("offset"))
|
||||
// limit: дефолт 100, потолок 1000 — иначе ошибка парсинга/омиссия = безлимит
|
||||
// (ревью 2026-10-10).
|
||||
limit := 100
|
||||
if v, err := strconv.Atoi(r.URL.Query().Get("limit")); err == nil && v > 0 {
|
||||
limit = v
|
||||
}
|
||||
if limit > 1000 {
|
||||
limit = 1000
|
||||
}
|
||||
offset := 0
|
||||
if v, err := strconv.Atoi(r.URL.Query().Get("offset")); err == nil && v > 0 {
|
||||
offset = v
|
||||
}
|
||||
|
||||
devices, err := h.Devices.List(r.Context(), ns, limit, offset)
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user