Repository /metrics/ endpoint is slow (3x COUNT(DISTINCT) + per-row REGEXP_REPLACE), times out under concurrent polling
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 25/100
- Issue type
- Refactor
- Clarity
- Mostly clear
- Activity status
- Active
- Domain
- databases, performance
Research direction
Start at MavenRepositoryViewSet.metrics and repository_metrics in pulp_maven/app/catalog.py, then read base_version_annotation and maven_packages_in_version to see how the queryset is built. Work out how the three .distinct().count() calls can share one aggregation while returning the same package_count, version_count and build_count. Done when the endpoint returns identical numbers from a single query and the existing metrics tests still pass.
Written by the indexing model from the issue text.
Description
Summary
The repository metrics endpoint (GET /pulp/api/v3/repositories/maven/maven/<pk>/metrics/) is expensive on large repositories. In production it takes ~15s for a large repo on a single call and spikes to ~45s when polled concurrently, exceeding the 30s CDN gateway timeout and surfacing as 504 Gateway Timeout to clients (the origin still returns 200 ~15s later).
Root cause
MavenRepositoryViewSet.metrics calls repository_metrics(maven_packages_in_version(repo_version)) in pulp_maven/app/catalog.py, which runs three separate COUNT(DISTINCT …) aggregations over the repository's MavenPackage set:
def repository_metrics(content_qs):
content_qs = content_qs.order_by()
return {
"package_count": content_qs.values("group_id", "artifact_id").distinct().count(),
"version_count": (
content_qs.annotate(_base_version=base_version_annotation())
.values("group_id", "artifact_id", "_base_version")
.distinct()
.count()
),
"build_count": content_qs.values("group_id", "artifact_id", "version").distinct().count(),
}
Issues:
- Three full passes. Each
.distinct().count()is a separate scan + hash/sort-distinct over the whole content set. - Per-row
REGEXP_REPLACE.version_countappliesbase_version_annotation()(aREGEXP_REPLACEonversion) to every row before the distinct — non-sargable, so no index can help it. pk__inmembership subquery.content_qscomes frommaven_packages_in_version()which isMavenPackage.objects.filter(pk__in=<memberships subquery>), producing a large intermediate set for big repositories.
The three aggregations are independent, so concurrent pollers multiply DB CPU/IO pressure, which is what pushes the latency from ~15s to ~45s.
Proposed fix
Collapse the three counts into a single pass, e.g. one aggregation over (group_id, artifact_id, version) that also carries a precomputed base_version, using conditional/Count(..., distinct=True) expressions, so the content set is scanned once and REGEXP_REPLACE is evaluated once per row instead of across a separate full pass. This removes two of the three scans and the duplicated regex work.
Impact
/metrics/is polled by automated clients (observed: anOpenAPI-GeneratorGo client polling every ~5 min with 3 concurrent requests), so the slow path recurs continuously and generates steady 504s at the edge even though there is no outage.- Affects any sufficiently large Maven repository.
Notes
- Code is unchanged since
repository_metricswas introduced; currentmainstill has this implementation.
- Dominant language
- Python
- Stars
- 5
- Forks
- 30
- Avg merge
- 2d 7h
- Merged PRs (30d)
- 36
Getting set up
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from pulp/pulp_maven
-
Instrument Maven path-index cache behaviorPossibly taken A pull request linked to this issue is open or already merged. Open
Difficulty 4/5 3-5 days Newbie friendliness 48/100
pulp/pulp_maven#570 ·
Maintainers usually reply within 1 day
-
Difficulty 5/5 Over a week Newbie friendliness 45/100
pulp/pulp_maven#568 ·
Maintainers usually reply within 1 day
-
Generated version-level maven-metadata.xml does not resolve SNAPSHOTs deployed under timestamped namesPossibly taken @aevnsvi claimed this 2 days ago. Open
Difficulty 4/5 3-5 days Newbie friendliness 55/100
pulp/pulp_maven#563 ·
Maintainers usually reply within 1 day
-
Redeploying the same coordinates with different content returns 201 but keeps serving the old filePossibly taken @aevnsvi claimed this 19 days ago. Open
Difficulty 4/5 1-2 days Newbie friendliness 58/100
pulp/pulp_maven#551 ·
Maintainers usually reply within 1 day
-
Directory index pages keep listing directories whose content was removedPossibly taken @aevnsvi claimed this 19 days ago. Open
Difficulty 4/5 3-5 days Newbie friendliness 20/100
pulp/pulp_maven#549 ·
Maintainers usually reply within 1 day
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
huggingface/accelerate#4511 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
pylint-dev/pylint#11791 ·
Maintainers usually reply within 1 day
-
Rasterio granule reads never retry, so one 503 (Service Unavailable) fails the whole requestPossibly taken @chuckwondo claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
developmentseed/titiler-cmr#305 ·
Maintainers usually reply within 1 day
-
community enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 1 day