Skip to content

Commit 163ab11

Browse files
author
Tejas Saubhage
committed
Add import history cleanup task and max_import_history setting fixes #13776
1 parent d015ea9 commit 163ab11

File tree

4 files changed

+65
-1
lines changed

4 files changed

+65
-1
lines changed
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
from django.db import migrations, models
2+
3+
4+
class Migration(migrations.Migration):
5+
6+
dependencies = [
7+
("dojo", "0261_remove_url_insert_insert_remove_url_update_update_and_more"),
8+
]
9+
10+
operations = [
11+
migrations.AddField(
12+
model_name="system_settings",
13+
name="max_import_history",
14+
field=models.IntegerField(
15+
blank=True,
16+
null=True,
17+
default=None,
18+
verbose_name="Max Import History",
19+
help_text="When set, the oldest import history records will be deleted when a test exceeds this number of imports. Leave empty to keep all history.",
20+
),
21+
),
22+
]

dojo/models.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,9 @@ class System_Settings(models.Model):
325325
"issue reaches the maximum "
326326
"number of duplicates, the "
327327
"oldest will be deleted. Duplicate will not be deleted when left empty. A value of 0 will remove all duplicates."))
328+
max_import_history = models.IntegerField(blank=True, null=True, default=None,
329+
verbose_name=_("Max Import History"),
330+
help_text=_("When set, the oldest import history records will be deleted when a test exceeds this number of imports. Leave empty to keep all history."))
328331

329332
email_from = models.CharField(max_length=200, default="no-reply@example.com", blank=True)
330333

dojo/settings/settings.dist.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,7 @@
280280
# we limit the amount of duplicates that can be deleted in a single run of that job
281281
# to prevent overlapping runs of that job from occurrring
282282
DD_DUPE_DELETE_MAX_PER_RUN=(int, 200),
283+
DD_IMPORT_HISTORY_MAX_PER_OBJECT=(int, 200),
283284
# when enabled 'mitigated date' and 'mitigated by' of a finding become editable
284285
DD_EDITABLE_MITIGATED_DATA=(bool, False),
285286
# new feature that tracks history across multiple reimports for the same test
@@ -1769,6 +1770,7 @@ def saml2_attrib_map_format(din):
17691770
DEDUPLICATION_ALGORITHM_PER_PARSER[key] = value
17701771

17711772
DUPE_DELETE_MAX_PER_RUN = env("DD_DUPE_DELETE_MAX_PER_RUN")
1773+
IMPORT_HISTORY_MAX_PER_OBJECT = env("DD_IMPORT_HISTORY_MAX_PER_OBJECT")
17721774

17731775
DISABLE_FINDING_MERGE = env("DD_DISABLE_FINDING_MERGE")
17741776

dojo/tasks.py

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,44 @@ def jira_status_reconciliation_task(*args, **kwargs):
207207
return jira_status_reconciliation(*args, **kwargs)
208208

209209

210-
@app.task
210+
211+
@app.task(bind=True)
212+
def async_import_history_cleanup(*args, **kwargs):
213+
with pghistory.context(source="import_history_cleanup_task"):
214+
_async_import_history_cleanup_impl()
215+
216+
217+
def _async_import_history_cleanup_impl():
218+
"""Delete oldest Test_Import records when a test exceeds max_import_history."""
219+
try:
220+
system_settings = System_Settings.objects.get()
221+
max_history = system_settings.max_import_history
222+
max_per_run = settings.IMPORT_HISTORY_MAX_PER_OBJECT
223+
except System_Settings.DoesNotExist:
224+
return
225+
226+
if max_history is None:
227+
logger.info("skipping import history cleanup: max_import_history not configured")
228+
return
229+
230+
logger.info("cleaning up import history (max per test: %s, max deletes per run: %s)", max_history, max_per_run)
231+
232+
tests_with_excess = Test_Import.objects \
233+
.values("test") \
234+
.annotate(import_count=Count("id")) \
235+
.filter(import_count__gt=max_history)[:max_per_run]
236+
237+
total_deleted_count = 0
238+
for entry in tests_with_excess:
239+
test_id = entry["test"]
240+
imports = Test_Import.objects.filter(test_id=test_id).order_by("created")
241+
excess_count = entry["import_count"] - max_history
242+
for test_import in imports[:excess_count]:
243+
logger.debug("deleting Test_Import id %s for test %s", test_import.id, test_id)
244+
test_import.delete()
245+
total_deleted_count += 1
246+
247+
logger.info("total import history records deleted: %s", total_deleted_count)
211248
def fix_loop_duplicates_task(*args, **kwargs):
212249
# Wrap with pghistory context for audit trail
213250
with pghistory.context(source="fix_loop_duplicates"):

0 commit comments

Comments
 (0)