fix: purge rule version history after reset import

This commit is contained in:
wren
2026-05-21 22:22:25 +08:00
parent 1f1bccf3b3
commit 18717e8276
5 changed files with 89 additions and 3 deletions
@@ -483,6 +483,7 @@ class RuleConfigServiceImpl(IRuleConfigService):
SELECT id, oss_url
FROM leaudit_rule_versions
WHERE id = ANY(:version_ids)
AND deleted_at IS NULL
"""
),
{"version_ids": version_ids},
@@ -501,6 +502,7 @@ class RuleConfigServiceImpl(IRuleConfigService):
SELECT DISTINCT ON (rule_set_id) rule_set_id, id
FROM leaudit_rule_versions
WHERE rule_set_id = ANY(:rule_set_ids)
AND deleted_at IS NULL
ORDER BY rule_set_id, version_seq DESC, id DESC
"""
),
@@ -518,6 +520,7 @@ class RuleConfigServiceImpl(IRuleConfigService):
SELECT oss_url
FROM leaudit_rule_versions
WHERE id = :version_id
AND deleted_at IS NULL
LIMIT 1
"""
),
@@ -676,6 +679,7 @@ class RuleConfigServiceImpl(IRuleConfigService):
SELECT id
FROM leaudit_rule_versions
WHERE rule_set_id = :rule_set_id
AND deleted_at IS NULL
ORDER BY version_seq DESC, id DESC
LIMIT 1
"""
@@ -696,6 +700,7 @@ class RuleConfigServiceImpl(IRuleConfigService):
SELECT version_seq
FROM leaudit_rule_versions
WHERE id = :version_id
AND deleted_at IS NULL
LIMIT 1
"""
),
@@ -237,6 +237,7 @@ class RuleServiceImpl(IRuleService):
rv.published_at
FROM leaudit_rule_versions rv
WHERE rv.rule_set_id = :rule_set_id
AND rv.deleted_at IS NULL
ORDER BY rv.version_seq DESC, rv.id DESC
"""
),
@@ -258,6 +259,7 @@ class RuleServiceImpl(IRuleService):
JOIN leaudit_rule_sets rs ON rs.id = rv.rule_set_id
WHERE rs.rule_type = :rule_type
AND rs.deleted_at IS NULL
AND rv.deleted_at IS NULL
ORDER BY rv.version_seq DESC, rv.id DESC
"""
),
@@ -281,6 +283,7 @@ class RuleServiceImpl(IRuleService):
FROM leaudit_rule_versions rv
JOIN leaudit_rule_sets rs ON rs.id = rv.rule_set_id
WHERE rv.id = :version_id
AND rv.deleted_at IS NULL
LIMIT 1
"""
),
@@ -1087,6 +1090,7 @@ class RuleServiceImpl(IRuleService):
published_at
FROM leaudit_rule_versions
WHERE id = :version_id
AND deleted_at IS NULL
LIMIT 1
"""
),
@@ -1102,6 +1106,7 @@ class RuleServiceImpl(IRuleService):
SELECT id
FROM leaudit_rule_versions
WHERE rule_set_id = :rule_set_id
AND deleted_at IS NULL
ORDER BY version_seq DESC, id DESC
LIMIT 1
"""
Submodule legal-platform-frontend updated: fb2fb0b76a...1e35e98006
+72 -2
View File
@@ -482,7 +482,66 @@ async def _backup_rule_domain(session) -> Path:
return backup_path
async def reset_and_import_rules(root: Path, *, dry_run: bool, prune_oss: bool) -> None:
async def _purge_rule_history() -> int:
async with GetAsyncSession() as session:
await session.execute(
text(
"""
UPDATE leaudit_audit_runs ar
SET rule_version_id = rs.current_version_id,
rule_source_oss_url = COALESCE(current_rv.oss_url, ar.rule_source_oss_url),
rule_source_sha256 = COALESCE(current_rv.file_sha256, ar.rule_source_sha256),
rule_type_id = COALESCE(current_rv.metadata_type_id, ar.rule_type_id)
FROM leaudit_rule_sets rs
LEFT JOIN leaudit_rule_versions current_rv ON current_rv.id = rs.current_version_id
CROSS JOIN leaudit_rule_versions old_rv
WHERE old_rv.id = ar.rule_version_id
AND ar.rule_set_id = rs.id
AND old_rv.id <> rs.current_version_id
AND rs.current_version_id IS NOT NULL
"""
)
)
await session.execute(
text(
"""
UPDATE leaudit_rule_results rr
SET rule_version_id = ar.rule_version_id
FROM leaudit_audit_runs ar
CROSS JOIN leaudit_rule_versions old_rv
WHERE old_rv.id = rr.rule_version_id
AND rr.run_id = ar.id
AND old_rv.id <> ar.rule_version_id
"""
)
)
result = await session.execute(
text(
"""
DELETE FROM leaudit_rule_versions rv
WHERE NOT EXISTS (
SELECT 1
FROM leaudit_rule_sets rs
WHERE rs.current_version_id = rv.id
)
AND NOT EXISTS (
SELECT 1
FROM leaudit_audit_runs ar
WHERE ar.rule_version_id = rv.id
)
AND NOT EXISTS (
SELECT 1
FROM leaudit_rule_results rr
WHERE rr.rule_version_id = rv.id
)
"""
)
)
await session.commit()
return int(result.rowcount or 0)
async def reset_and_import_rules(root: Path, *, dry_run: bool, prune_oss: bool, purge_rule_history: bool) -> None:
local_rules = load_local_rules(root)
canonical_keys = {
OssPathUtils.BuildRuleYamlKey(local.rule_type, local.version_no)
@@ -572,6 +631,9 @@ async def reset_and_import_rules(root: Path, *, dry_run: bool, prune_oss: bool)
print("oss_deleted=0")
await import_rules(root, dry_run=False)
if purge_rule_history:
deleted = await _purge_rule_history()
print(f"purged_rule_versions={deleted}")
def main() -> None:
@@ -580,9 +642,17 @@ def main() -> None:
parser.add_argument("--execute", action="store_true")
parser.add_argument("--reset-rule-domain", action="store_true")
parser.add_argument("--prune-oss", action="store_true")
parser.add_argument("--purge-rule-history", action="store_true")
args = parser.parse_args()
if args.reset_rule_domain:
asyncio.run(reset_and_import_rules(Path(args.root), dry_run=not args.execute, prune_oss=args.prune_oss))
asyncio.run(
reset_and_import_rules(
Path(args.root),
dry_run=not args.execute,
prune_oss=args.prune_oss,
purge_rule_history=args.purge_rule_history,
)
)
else:
asyncio.run(import_rules(Path(args.root), dry_run=not args.execute))
+6
View File
@@ -105,6 +105,12 @@ def test_assert_rollback_target_allows_previous_version():
service._assert_rollback_target(version_row, rule_set)
def test_rule_version_queries_exclude_soft_deleted_versions():
sql_text = str(RuleServiceImpl.GetVersions.__code__.co_consts)
assert "rv.deleted_at IS NULL" in sql_text
def test_tenant_user_requires_rule_tenant_schema_before_write():
service = RuleServiceImpl()