diff --git a/cvat/apps/engine/migrations/0084_honeypot_support.py b/cvat/apps/engine/migrations/0084_honeypot_support.py index 53b2be5e1e58..721d400ec386 100644 --- a/cvat/apps/engine/migrations/0084_honeypot_support.py +++ b/cvat/apps/engine/migrations/0084_honeypot_support.py @@ -1,9 +1,11 @@ # Generated by Django 4.2.15 on 2024-09-23 13:11 from typing import Collection +from collections import defaultdict import django.db.models.deletion from django.db import migrations, models +from django.db.models import Count, Q import cvat.apps.engine.models @@ -39,6 +41,28 @@ def get_segment_rel_frame_set(db_segment) -> Collection[int]: return sorted(get_rel_frame(abs_frame, db_data) for abs_frame in frame_set) +def delete_duplicate_ground_truth_jobs(apps, schema_editor): + Task = apps.get_model("engine", "Task") + Job = apps.get_model("engine", "Job") + + broken_tasks = Task.objects.annotate( + ground_truth_jobs_count=Count( + 'segment__job', filter=Q(segment__job__type='ground_truth') + ) + ).filter(ground_truth_jobs_count__gt=1) + + gt_jobs = Job.objects.filter( + segment__task__in=broken_tasks + ).filter(type='ground_truth').order_by('-updated_date').iterator(1000) + + groups = defaultdict(list) + for gt_job in gt_jobs: + assert gt_job.type == 'ground_truth' + groups[gt_job.segment.task.id].append(gt_job) + + for gt_jobs in groups.values(): + for gt_job in gt_jobs[1:]: + gt_job.delete() def init_validation_layout_in_tasks_with_gt_job(apps, schema_editor): Job = apps.get_model("engine", "Job") @@ -220,6 +244,10 @@ class Migration(migrations.Migration): ), ], ), + migrations.RunPython( + delete_duplicate_ground_truth_jobs, + reverse_code=migrations.RunPython.noop, + ), migrations.RunPython( init_validation_layout_in_tasks_with_gt_job, reverse_code=migrations.RunPython.noop,