perf(api): ретенция статистики, устранение N+1 и пагинация списков

- retention: ежедневный cron (03:17) + запуск на старте удаляет сырые
  agent_stats_samples старше STATS_RETENTION_DAYS (по умолчанию 30);
  lifetime-итоги на агенте и агрегаты сохраняются
- N+1 на поллинг-пути агента: evaluateAgentPolicy теперь делает по одному
  батч-запросу на записи списков / резолвы hostname / имена списков вместо
  запроса на каждое правило; mapPolicyRules и port-rules GET — аналогично
- пагинация: GET /agents, /lists, /rules, /install-links принимают
  limit/offset и возвращают total; без параметров — прежнее поведение
- openapi.yaml: approve-bulk, PUT /policy-sets/{id}/agents, параметры
  пагинации (redocly lint OK); тесты (47 passed)
This commit is contained in:
Denozordec
2026-09-20 19:20:30 +07:00
parent 454c5009d1
commit 7a3f1fad25
23 changed files with 462 additions and 85 deletions
+63 -4
View File
@@ -43,9 +43,12 @@ paths:
summary: List install links
tags: [agents]
security: [{ bearerAuth: [] }]
parameters:
- $ref: '#/components/parameters/Limit'
- $ref: '#/components/parameters/Offset'
responses:
'200':
description: Links
description: Links (items + total)
post:
summary: Create install link + invited agent
tags: [agents]
@@ -70,9 +73,33 @@ paths:
summary: List agents
tags: [agents]
security: [{ bearerAuth: [] }]
parameters:
- $ref: '#/components/parameters/Limit'
- $ref: '#/components/parameters/Offset'
responses:
'200':
description: Agents
description: Agents (items + total)
/api/v1/agents/approve-bulk:
post:
summary: Approve many pending/invited agents in one request
tags: [agents]
security: [{ bearerAuth: [] }]
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [agent_ids]
properties:
agent_ids:
type: array
maxItems: 1000
items: { type: string }
responses:
'200':
description: Approved agents (skips non-pending/invited)
/api/v1/agents/{id}:
get:
@@ -199,9 +226,12 @@ paths:
summary: List IP lists
tags: [lists]
security: [{ bearerAuth: [] }]
parameters:
- $ref: '#/components/parameters/Limit'
- $ref: '#/components/parameters/Offset'
responses:
'200':
description: Lists
description: Lists (items + total)
post:
summary: Create IP list
tags: [lists]
@@ -328,14 +358,33 @@ paths:
'200':
description: Reordered
/api/v1/policy-sets/{id}/agents:
put:
summary: Replace which agents have this set assigned
description: >-
Listed agents gain the set (other assignments preserved), unlisted
agents lose it. Body — { agent_ids: string[] } (empty array clears).
tags: [policies]
security: [{ bearerAuth: [] }]
parameters:
- $ref: '#/components/parameters/Id'
responses:
'200':
description: '{ agent_ids, added, removed }'
'404':
description: Set or agent not found
/api/v1/rules:
get:
summary: List policy rules (optional set filter)
tags: [policies]
security: [{ bearerAuth: [] }]
parameters:
- $ref: '#/components/parameters/Limit'
- $ref: '#/components/parameters/Offset'
responses:
'200':
description: Rules
description: Rules (items + total)
post:
summary: Create policy rule
tags: [policies]
@@ -787,6 +836,16 @@ components:
in: path
required: true
schema: { type: string }
Limit:
name: limit
in: query
schema: { type: integer, minimum: 1, maximum: 1000 }
description: Page size (without limit/offset the full list is returned)
Offset:
name: offset
in: query
schema: { type: integer, minimum: 0 }
description: Page offset (response includes total)
schemas:
AgentPortRule:
type: object