Skip to content

feat(strategy): 支持策略历史安全清理并完善批量操作记录 - #11627

Open
Liyuhnag wants to merge 17 commits into
TencentBlueKing:masterfrom
Liyuhnag:feat/strategy-history-cleanup
Open

feat(strategy): 支持策略历史安全清理并完善批量操作记录#11627
Liyuhnag wants to merge 17 commits into
TencentBlueKing:masterfrom
Liyuhnag:feat/strategy-history-cleanup

Conversation

@Liyuhnag

Copy link
Copy Markdown
Contributor

背景

策略历史表持续记录策略的创建、更新和删除操作。随着策略数量和变更频率增长,历史数据不断累积,目前缺少安全、可控的过期数据清理机制。

历史记录不能简单按时间全部删除:

  • 现存策略需要保留可用于恢复的有效配置快照。
  • 已删除策略需要保留删除前快照及最终删除记录。
  • 失败记录、空内容记录不能作为有效快照。
  • 一次性扫描或删除大量数据可能给数据库带来较大压力。
  • 旧版批量操作历史未正确区分操作类型和成功状态,需要兼容处理。

改动内容

1. 新增策略历史清理逻辑

仅清理指定时间窗口之前的过期历史,窗口内记录全部保留。

对于窗口外的数据:

  • 每个策略保留最近 N 条 status=Truecontent 非空的有效快照。
  • 快照操作包括 createupdatebulk_update
  • 已删除策略额外保留最新一条 deletebulk_delete 记录。
  • 失败记录、空内容记录、非快照操作及多余旧快照允许被清理。
  • 创建时间相同时按 ID 倒序确定先后,保证清理结果稳定。
  • 支持重复执行,相同参数下具有幂等性。

2. 控制数据库处理压力

  • strategy_id 分片扫描存在过期历史的策略。
  • 按主键顺序分批删除,避免一次加载或删除大量记录。
  • 支持配置单批删除数量和每个策略保留的快照数量。
  • 默认仅执行 dry-run,防止管理命令误操作。

3. 新增管理命令

新增 clean_strategy_history

python manage.py clean_strategy_history \
  --days 30 \
  --batch_size 1000 \
  --keep_latest_snapshots 1

参数说明:

  • --days:保留最近 N 天的全部历史,最小为 30 天。
  • --batch_size:单批删除数量,默认 1000。
  • --keep_latest_snapshots:每个策略保留的有效快照数量,默认 1。
  • --execute:执行真实删除;未传入时默认 dry-run,仅统计预计删除数量。

建议先执行 dry-run:

python manage.py clean_strategy_history \
  --days 30 \
  --batch_size 1000 \
  --keep_latest_snapshots 1

确认预计删除数量后,再执行真实清理:

python manage.py clean_strategy_history \
  --days 30 \
  --batch_size 1000 \
  --keep_latest_snapshots 1 \
  --execute

4. 兼容旧版批量操作历史

新增临时兼容命令 clean_strategy_history_compat

旧版批量更新历史复用了 update 类型,且成功状态未正确回写。兼容命令会为窗口外满足以下条件的旧记录提供独立的快照保留名额:

  • operate=update
  • status=False
  • message 为空
  • content 非空

该命令默认同样为 dry-run,仅用于旧数据仍需兼容的过渡阶段。兼容期结束后应停用,恢复使用标准清理命令。

5. 完善批量操作历史记录

新增操作类型:

  • bulk_update
  • bulk_delete

批量操作成功历史统一写入 status=True,使清理逻辑能够准确识别有效快照和删除记录。

同时完成以下适配:

  • 策略缓存识别 bulk_delete 并正确清理缓存。
  • AIOPS 同步识别 bulk_delete 并发送删除事件。
  • 普通操作与批量操作历史类型保持明确区分。

6. 保证业务数据与历史记录一致

批量更新、批量删除及成功历史写入使用同一数据库事务:

  • 任意业务数据操作失败时,不写入成功历史。
  • 成功历史写入失败时,业务数据同步回滚。
  • 事务数据库根据运行时数据库路由动态确定,兼容数据库路由覆盖场景。

清理规则

场景 保留内容
现存策略 窗口内全部历史,以及最近 N 条有效快照
已删除策略 窗口内全部历史、最近 N 条有效快照、最新删除记录
失败历史 窗口外允许清理
空内容历史 不占用有效快照名额
同一创建时间 ID 较大的记录视为更新记录
重复执行 已保留记录不会被再次删除

验证

策略历史相关测试:

61 passed

主要覆盖以下场景:

清理规则

  • 现存策略保留最近有效配置快照。
  • 已删除策略保留最近有效快照和最新删除记录。
  • 窗口内存在有效快照时,正确处理窗口外快照。
  • keep_latest_snapshots > 1 时正确保留多个历史版本。
  • 失败记录、空内容记录和非快照操作不占用保留名额。

操作类型与边界

  • 正确处理 createupdatebulk_update 混合历史。
  • 正确处理 deletebulk_delete 混合历史。
  • 截止时间使用严格小于判断,边界记录不会被删除。
  • 创建时间相同时按 ID 稳定选择。
  • 覆盖现存策略、已删除策略及 strategy_id=0 场景。

分片与批量删除

  • 多个策略分片处理时不遗漏、不重复。
  • 非连续主键场景下正确分批删除。
  • 无过期历史时返回 0。
  • 相同参数重复执行保持幂等。

dry-run 与管理命令

  • 默认 dry-run 仅返回预计删除数量,不修改数据库。
  • 传入 --execute 后正确执行真实删除。
  • 正确传递保留天数、删除批次和快照数量。
  • 正确校验最小保留天数及参数类型、取值范围。
  • 正确输出预计删除数量和实际删除数量。

事务与下游兼容

  • 批量更新、批量删除失败时事务正确回滚。
  • 动态数据库路由场景下事务使用正确数据库。
  • 策略缓存和 AIOPS 同步正确处理 bulk_delete

其他检查:

  • Ruff:通过。
  • git diff --check:通过。

@tencentblueking-adm

tencentblueking-adm commented Jul 22, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@Liyuhnag Liyuhnag changed the title Feat/strategy history cleanup feat(strategy): 支持策略历史安全清理并完善批量操作记录 Jul 22, 2026
@github-actions

Copy link
Copy Markdown

请在 PR 中添加项目标签,例如:project/monitorproject/apmproject/logproject/publicproject/aiops

@github-actions

Copy link
Copy Markdown

请在 PR 中添加类型标签,例如:fixfeatdocsstylerefactortestchoremerge, perf

@unique0lai
unique0lai requested a review from Copilot July 22, 2026 04:10
@unique0lai unique0lai added project/monitor project monitor feat A new feature. Correlates with MINOR in SemVer labels Jul 22, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

该 PR 为策略历史(StrategyHistoryModel)引入“可控、安全、可重复执行”的过期数据清理机制,并补齐批量更新/删除在历史记录、缓存刷新与 AIOPS 同步侧的操作类型与事务一致性,避免历史表无限增长且清理误删可恢复快照。

Changes:

  • 新增策略历史清理核心逻辑与两类管理命令(标准清理 + 旧数据兼容清理),支持 dry-run、分片扫描与分批删除。
  • 批量更新/批量删除补齐历史操作类型(bulk_update/bulk_delete)并将“成功历史写入”与“业务写入/删除”纳入同一数据库事务。
  • 策略缓存与 AIOPS 同步流程适配 bulk_delete,新增较完整的单测覆盖清理边界与事务路由场景。

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
bkmonitor/packages/monitor_web/strategies/resources/v2.py 批量局部更新增加按路由库开启事务,并将历史类型改为 bulk_update 且写入成功状态
bkmonitor/bkmonitor/strategy/new_strategy.py 批量删除增加按路由库开启事务,历史类型改为 bulk_delete 且成功状态写入置 True,并调整写入时机到删除完成后
bkmonitor/bkmonitor/strategy/history.py 新增策略历史清理核心实现:保留窗口内历史、保留最近 N 条有效快照、为已删策略保留最新删除记录,支持兼容模式与批量删除
bkmonitor/bkmonitor/models/strategy.py 扩展 StrategyHistoryModel.operate choices,增加 bulk_update/bulk_delete
bkmonitor/bkmonitor/management/commands/clean_strategy_history.py 新增标准清理管理命令:默认 dry-run,参数校验与输出
bkmonitor/bkmonitor/management/commands/clean_strategy_history_compat.py 新增兼容清理命令:在标准规则上额外兼容旧批量更新/删除状态问题,并输出弃用提示
bkmonitor/alarm_backends/core/cache/strategy.py 缓存刷新与 AIOPS 同步适配 bulk_delete 操作类型
bkmonitor/bkmonitor/strategy/tests/test_strategy_history.py 新增批量更新/删除历史类型、事务路由与缓存处理的单测
bkmonitor/bkmonitor/strategy/tests/test_history_cleanup.py 新增清理规则与兼容规则的单测覆盖
bkmonitor/bkmonitor/strategy/tests/test_history_cleanup_command.py 新增管理命令参数传递、dry-run/execute、错误处理的单测覆盖
bkmonitor/bkmonitor/strategy/tests/test_clean_strategy_history_boundaries.py 新增清理边界矩阵(窗口边界、幂等、分片、PK 空洞批删、命令端到端)的单测覆盖

Comment on lines +180 to +195
model = queryset.model
last_pk = None
deleted = 0

while True:
batch = queryset.order_by("pk")
if last_pk is not None:
batch = batch.filter(pk__gt=last_pk)

history_ids = list(batch.values_list("pk", flat=True)[:batch_size])
if not history_ids:
return deleted

deleted_count, _ = model._default_manager.filter(pk__in=history_ids).delete()
deleted += deleted_count
last_pk = history_ids[-1]

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated no new comments.

@unique0lai unique0lai left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

发现 1 个滚动发布/回滚兼容性问题,详见 inline comment。

create_user=cls._get_username(),
strategy_id=strategy_id,
operate="delete",
operate="bulk_delete",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] 这里开始写入 operate="bulk_delete",但旧版本的 StrategyCacheManager 只把 "delete" 识别为删除;其余类型会读取 content["bk_biz_id"]content["items"]。由于这条历史的 content 为空,在 Web 与 alarm backend 滚动发布、或版本回滚时,旧 consumer 会触发 KeyError,缓存增量刷新也可能因更新时间不再推进而持续失败。建议拆成两阶段发布:先让所有 reader 兼容 bulk_delete,后续版本再启用 writer;或者暂时继续写 delete,通过 feature flag 延迟新类型。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feat A new feature. Correlates with MINOR in SemVer project/monitor project monitor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants