Skip to content

refactor(auth): give coalesced API-key usage stats their own service - #1026

Merged
rmyndharis merged 1 commit into
mainfrom
refactor/api-key-usage-tracker
Jul 31, 2026
Merged

refactor(auth): give coalesced API-key usage stats their own service#1026
rmyndharis merged 1 commit into
mainfrom
refactor/api-key-usage-tracker

Conversation

@rmyndharis

Copy link
Copy Markdown
Owner

Why

pendingUsage was the one piece of state shared between three concerns that change for entirely
different reasons:

  • the per-request authentication hot path incremented it (auth.service.ts:522-546),
  • admin key lifecycle dropped a deleted or revoked key's counters (:367, :394),
  • shutdown flushed whatever was left (:141-172).

That shared map is what made AuthService a god object rather than merely a large one — the concerns
otherwise touch none of the same state.

What moves

ApiKeyUsageTracker owns the map, both window constants, the windowed save and the bounded shutdown
flush.

record() takes the entity, not an id: the hot path mutates lastUsedAt/usageCount on the
instance validateApiKey is about to return, so the response reflects the true count including
increments still pending. forget(keyId) replaces the two lifecycle deletes.

AuthService keeps a one-line onModuleDestroy that delegates. Five spec callsites drive shutdown
through it (spec:713, :729, :732, :737, :749), and it is the natural owner of the Nest hook — the
tracker exposes flushOnShutdown() rather than implementing the hook itself, so the flush has exactly
one trigger rather than two.

Scope

572 → 505 lines; grep -c pendingUsage auth.service.ts returns 0.

Behaviour is identical — the coalescing window, the lost-update merge that re-accumulates on a failed
windowed write, and the 5s bounded shutdown flush all moved verbatim.

Spec change is two lines: the provider and its import. No assertion, harness or fixture was touched.
141 auth tests pass.

Remaining

auth.service.ts still has one spanning item — the API_KEY_FILE module const derived from
process.cwd(), shared between operator bootstrap and admin lifecycle. That is a separate change and
carries a real e2e defect with it: test/setup-e2e.ts redirects both SQLite databases but has no lever
for this path, so an e2e boot rewrites the developer's repo-root data/.api-key. Fixing it means making
the path injected rather than a const, which is why it is not bundled here.

Verification

Backend lint, prettier --check, tsc --noEmit over the full project including specs, build, 4012 unit
tests, 137 e2e tests, and the dashboard build all pass on Node 22.

pendingUsage was the one piece of state shared between three concerns that
change for entirely different reasons: the per-request authentication hot path
that incremented it, admin key lifecycle that dropped a deleted or revoked key's
counters, and shutdown that flushed whatever was left. That is what made
AuthService a god object rather than a large one.

ApiKeyUsageTracker owns the map, the two window constants, the windowed save and
the bounded shutdown flush. record() takes the ENTITY rather than an id, because
the hot path mutates lastUsedAt/usageCount on the instance validateApiKey is
about to return so the response reflects the true count including pending
increments. forget(keyId) replaces the two lifecycle deletes.

AuthService keeps a one-line onModuleDestroy that delegates. Five spec callsites
drive shutdown through it, and it is the natural owner of the Nest hook — the
tracker exposes flushOnShutdown() rather than implementing the hook itself, so
the flush has exactly one trigger.

572 to 505 lines, and grep for pendingUsage in auth.service.ts returns nothing.
Behaviour identical: the coalescing window, the lost-update merge on a failed
windowed write, and the 5s shutdown bound all moved verbatim.

Spec change is two lines — the provider and its import. No assertion, harness or
fixture was touched; 141 auth tests pass.
@rmyndharis
rmyndharis merged commit 1b8ca86 into main Jul 31, 2026
15 checks passed
@rmyndharis
rmyndharis deleted the refactor/api-key-usage-tracker branch July 31, 2026 18:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant