feat: per-developer billing concurrency stat endpoints (GrantFox FWC26) - #849
Closed
eliassmthl-collab wants to merge 1 commit into
Closed
feat: per-developer billing concurrency stat endpoints (GrantFox FWC26)#849eliassmthl-collab wants to merge 1 commit into
eliassmthl-collab wants to merge 1 commit into
Conversation
Implements GET /api/admin/metrics/concurrency and GET /api/admin/metrics/concurrency/:developerId backed by the shared billingConcurrencySemaphore so counts reflect live billing traffic. Changes: - src/utils/developerSemaphore.ts: add getActiveSlotCount(), getQueueLength(), and isAtLimit() methods to DeveloperSemaphore - src/routes/admin/metrics.ts: createAdminMetricsConcurrencyRouter() factory with list + detail endpoints; DI for test isolation; structured audit logging with correlation ID, client IP, user agent - src/routes/admin.ts: mount /metrics router - src/routes/admin/metrics.test.ts: 14 focused tests covering empty state, single/multi-slot, multi-developer, slot release, atLimit flag, auth guard, and campaign label - README.md: document the two new admin endpoints Closes #608
eliassmthl-collab
force-pushed
the
task/concurrency-stat
branch
from
July 26, 2026 21:22
935ed09 to
c78ae38
Compare
|
@eliassmthl-collab Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements per-developer billing concurrency stat endpoints for the GrantFox FWC26 campaign (issue #608).
Admins can now inspect live billing concurrency pressure per developer in real time — useful for diagnosing overdraft guards, rate-limit tuning, and on-call triage.
Endpoints
GET /api/admin/metrics/concurrencyReturns a real-time snapshot of active billing slot counts for all developers currently holding (or recently holding) a slot. Developers with zero active slots are omitted to keep the payload compact.
{ "data": { "developerCounts": { "dev_abc": 1, "dev_xyz": 2 }, "totalActive": 3, "campaign": "GrantFox FWC26" } }GET /api/admin/metrics/concurrency/:developerIdReturns the active slot count, queue depth, and at-limit flag for a single developer. Safe to call for unknown IDs — returns zeros rather than 404.
{ "data": { "developerId": "dev_abc", "activeCount": 1, "queueLength": 0, "atLimit": true, "campaign": "GrantFox FWC26" } }Both endpoints require admin auth (
x-admin-api-key) and are protected by the IP allowlist — inherited from the parent admin router, no duplicate guard needed.Changes
src/utils/developerSemaphore.tsAdded three public introspection methods, mirroring the existing
KeySemaphoreAPI:getActiveSlotCount(developerId)— active slots for one developer, 0 if not trackedgetQueueLength(developerId)— requests waiting for a slot (queue depth)isAtLimit(developerId)— whether the developer has exhausted their concurrency budgetThese are read-only; they do not affect semaphore behaviour.
src/routes/admin/metrics.ts(new)Router factory
createAdminMetricsConcurrencyRouter(deps?)with:DeveloperSemaphoreinstance; defaults to the sharedbillingConcurrencySemaphorefrombilling.tsso production sees live traffic without any wiringdeveloperIdis non-empty before the handler runslogger.audit()event with event name, actor, client IP, User-Agent, andx-request-id/x-correlation-idfor full traceabilityAppErrorsubtypes propagate vianext(); unexpected errors are wrapped inInternalServerErrorand logged before forwardingsrc/routes/admin.tsImported and mounted the new router at
/metrics.src/routes/admin/metrics.test.ts(new)14 focused unit tests covering:
atLimit: truewhen concurrency limit is saturateddeveloperIdpath segment falls through gracefullycampaignlabel present in both response shapesTests use an isolated
DeveloperSemaphoreinstance (not the singleton) so they are fully independent and do not affect each other or production state.README.mdDocumented both endpoints in the "What's included" section alongside the existing admin endpoints.
Test output
Lint: clean on all changed files (
eslintexits 0).Security notes
developerIdin audit logs comes from validated route params, not raw user inputCloses #608