|
30 | 30 | UsageTrendData, |
31 | 31 | ) |
32 | 32 | from projects.models import Project |
| 33 | +from projects.tags.models import TagType |
33 | 34 | from users.models import FFAdminUser |
34 | 35 |
|
35 | 36 | logger = structlog.get_logger("platform_hub") |
@@ -355,29 +356,34 @@ def get_organisation_metrics( |
355 | 356 | return results |
356 | 357 |
|
357 | 358 |
|
358 | | -def _get_stale_flag_counts_by_org( |
| 359 | +def _get_stale_flag_counts_by_project( |
359 | 360 | organisations: QuerySet[Organisation], |
360 | 361 | ) -> dict[int, int]: |
361 | | - """Return a mapping of organisation_id -> stale flag count.""" |
362 | | - projects = Project.objects.filter( |
363 | | - organisation__in=organisations, |
364 | | - ).values("id", "organisation_id", "stale_flags_limit_days") |
| 362 | + """Return a mapping of project_id -> stale flag count.""" |
| 363 | + return dict( |
| 364 | + Feature.objects.filter( |
| 365 | + project__organisation__in=organisations, |
| 366 | + tags__type=TagType.STALE, |
| 367 | + ) |
| 368 | + .values("project_id") |
| 369 | + .annotate(count=Count("id", distinct=True)) |
| 370 | + .values_list("project_id", "count") |
| 371 | + ) |
365 | 372 |
|
366 | | - result: dict[int, int] = defaultdict(int) |
367 | | - for project in projects: |
368 | | - cutoff = timezone.now() - timedelta(days=project["stale_flags_limit_days"]) |
369 | 373 |
|
370 | | - stale_count = ( |
371 | | - Feature.objects.filter(project_id=project["id"]) |
372 | | - .exclude( |
373 | | - feature_states__updated_at__gte=cutoff, |
374 | | - ) |
375 | | - .distinct() |
376 | | - .count() |
| 374 | +def _get_stale_flag_counts_by_org( |
| 375 | + organisations: QuerySet[Organisation], |
| 376 | +) -> dict[int, int]: |
| 377 | + """Return a mapping of organisation_id -> stale flag count.""" |
| 378 | + return dict( |
| 379 | + Feature.objects.filter( |
| 380 | + project__organisation__in=organisations, |
| 381 | + tags__type=TagType.STALE, |
377 | 382 | ) |
378 | | - result[project["organisation_id"]] += stale_count |
379 | | - |
380 | | - return result |
| 383 | + .values("project__organisation_id") |
| 384 | + .annotate(count=Count("id", distinct=True)) |
| 385 | + .values_list("project__organisation_id", "count") |
| 386 | + ) |
381 | 387 |
|
382 | 388 |
|
383 | 389 | def _get_integration_counts_by_org( |
@@ -501,27 +507,21 @@ def get_stale_flags_per_project( |
501 | 507 | .values_list("project_id", "count") |
502 | 508 | ) |
503 | 509 |
|
| 510 | + stale_counts_by_project = _get_stale_flag_counts_by_project(organisations) |
| 511 | + |
504 | 512 | results: list[StaleFlagsPerProjectData] = [] |
505 | 513 | for project in projects: |
506 | 514 | total_flags = flag_counts_by_project.get(project.id, 0) |
507 | 515 | if total_flags == 0: |
508 | 516 | continue |
509 | 517 |
|
510 | | - cutoff = timezone.now() - timedelta(days=project.stale_flags_limit_days) |
511 | | - stale_flags = ( |
512 | | - Feature.objects.filter(project=project) |
513 | | - .exclude(feature_states__updated_at__gte=cutoff) |
514 | | - .distinct() |
515 | | - .count() |
516 | | - ) |
517 | | - |
518 | 518 | results.append( |
519 | 519 | StaleFlagsPerProjectData( |
520 | 520 | organisation_id=project.organisation_id, |
521 | 521 | organisation_name=project.organisation.name, |
522 | 522 | project_id=project.id, |
523 | 523 | project_name=project.name, |
524 | | - stale_flags=stale_flags, |
| 524 | + stale_flags=stale_counts_by_project.get(project.id, 0), |
525 | 525 | total_flags=total_flags, |
526 | 526 | ) |
527 | 527 | ) |
|
0 commit comments