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

1"""Prune outbox rows past the configured retention limits.""" 

2 

3from __future__ import annotations 

4 

5from django.core.management.base import BaseCommand 

6from django.core.management.base import CommandError 

7from django.db import DEFAULT_DB_ALIAS 

8 

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 

13 

14 

15class Command(BaseCommand): 

16 help = "Delete object stream outbox rows past the configured retention limits." 

17 

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 ) 

41 

42 def handle(self, *args, **options): 

43 database = options["database"] 

44 dry_run = options["dry_run"] 

45 verbosity = int(options["verbosity"]) 

46 

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 

52 

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) 

60 

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 

66 

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