# Generated by Django 4.2.25 on 2025-11-24 06:03 from django.db import migrations, transaction from django.db.models import OuterRef, Subquery import logging logger = logging.getLogger("plane.migrations") BATCH_SIZE = 4000 def create_triage_state(apps, _schema_editor): Project = apps.get_model("db", "Project") State = apps.get_model("db", "State") Issue = apps.get_model("db", "Issue") # 1) Bulk-update existing triage states triage_qs = State.objects.filter(group="triage") projects_with_triage_state = list(triage_qs.values_list("project_id", flat=True)) triage_qs.update( name="Triage", color="#4E5355", sequence=65000, default=False, ) logger.info(f"Updated {triage_qs.count()} triage states.") # 2) Projects that already have a 'Triage' name but not in triage group projects_to_update_qs = ( State.objects.exclude(group="triage") .filter(name="Triage") .values_list("project_id", flat=True) ) projects_to_update = set(projects_to_update_qs) logger.info(f"Projects to update: {len(projects_to_update)}") # 3) Create missing triage states in chunks to avoid memory spike states_to_create = [] project_iter = Project.objects.all().values_list("id", "workspace_id").iterator() for proj_id, workspace_id in project_iter: if proj_id in projects_with_triage_state: continue if proj_id in projects_to_update: name = f"Triage-{str(proj_id)[:5]}" else: name = "Triage" states_to_create.append( State( name=name, group="triage", project_id=proj_id, workspace_id=workspace_id, color="#4E5355", sequence=65000, default=False, ) ) if len(states_to_create) >= BATCH_SIZE: State.objects.bulk_create(states_to_create, batch_size=BATCH_SIZE) states_to_create = [] if states_to_create: State.objects.bulk_create(states_to_create, batch_size=BATCH_SIZE) # 4) Update issues: use deterministic subquery and only update issues that will get a triage state. with transaction.atomic(): triage_state_subquery = ( State.objects.filter( group="triage", project_id=OuterRef("project_id"), workspace_id=OuterRef("workspace_id"), ) .values("id")[:1] ) updated_count = Issue._default_manager.filter( issue_intake__status__in=[-2, 0], ).update(state_id=Subquery(triage_state_subquery)) logger.info(f"Updated {updated_count} issues.") class Migration(migrations.Migration): dependencies = [ ('db', '0111_notification_notif_receiver_status_idx_and_more'), ] operations = [ migrations.RunPython(create_triage_state, reverse_code=migrations.RunPython.noop), ]