Coverage for object_streams/management/commands/object_streams_prune.py: 100%
36 statements
« prev ^ index » next coverage.py v7.16.0, created at 2026-09-02 17:07 +0000
« prev ^ index » next coverage.py v7.16.0, created at 2026-09-02 17:07 +0000
1"""Prune outbox rows past the configured retention limits."""
3from __future__ import annotations
5from django.core.management.base import BaseCommand
6from django.core.management.base import CommandError
7from django.db import DEFAULT_DB_ALIAS
9from object_streams.retention import get_retention_days
10from object_streams.retention import get_retention_max_rows
11from object_streams.retention import prune_outbox
12from object_streams.retention import retention_cutoff
15class Command(BaseCommand):
16 help = "Delete object stream outbox rows past the configured retention limits."
18 def add_arguments(self, parser):
19 parser.add_argument(
20 "--database",
21 default=DEFAULT_DB_ALIAS,
22 help="Database alias to prune.",
23 )
24 parser.add_argument(
25 "--days",
26 default=None,
27 type=int,
28 help="Age limit in days. Defaults to OBJECT_STREAMS_RETENTION_DAYS.",
29 )
30 parser.add_argument(
31 "--max-rows",
32 default=None,
33 type=int,
34 help="Row limit for the outbox. Defaults to OBJECT_STREAMS_RETENTION_MAX_ROWS.",
35 )
36 parser.add_argument(
37 "--dry-run",
38 action="store_true",
39 help="Report how many rows would be deleted without deleting them.",
40 )
42 def handle(self, *args, **options):
43 database = options["database"]
44 dry_run = options["dry_run"]
45 verbosity = int(options["verbosity"])
47 try:
48 days = options["days"] if options["days"] is not None else get_retention_days()
49 max_rows = options["max_rows"] if options["max_rows"] is not None else get_retention_max_rows()
50 except ValueError as exc:
51 raise CommandError(str(exc)) from exc
53 if days is None and max_rows is None:
54 msg = (
55 "No retention limit is configured. "
56 "Set OBJECT_STREAMS_RETENTION_DAYS or OBJECT_STREAMS_RETENTION_MAX_ROWS, "
57 "or pass --days or --max-rows."
58 )
59 raise CommandError(msg)
61 try:
62 before = retention_cutoff(days) if days is not None else None
63 deleted = prune_outbox(before=before, max_rows=max_rows, using=database, dry_run=dry_run)
64 except ValueError as exc:
65 raise CommandError(str(exc)) from exc
67 if verbosity >= 1:
68 action = "Would delete" if dry_run else "Deleted"
69 self.stdout.write(f"{action} {deleted} object stream outbox rows.")
70 return None