Skip to content

perf(server): coalesce metrics queries and handle empty series - #1710

Open
OskarEichler wants to merge 3 commits into
OutlineFoundation:masterfrom
OskarEichler:codex/metrics-query-coalescing
Open

OskarEichler wants to merge 3 commits into
OutlineFoundation:masterfrom
OskarEichler:codex/metrics-query-coalescing

Conversation

@OskarEichler

@OskarEichler OskarEichler commented Aug 27, 2026

Copy link
Copy Markdown

Why

Concurrent dashboard reads issue the same Prometheus queries independently. Empty bandwidth results and negative-infinity peak samples can also dereference absent values.

Changes

  • Replace per-access dynamic proxies with a typed cached client.
  • Cache pending queries, retain the existing five-minute result lifetime, and evict rejected entries so later requests retry.
  • Handle absent bandwidth series and guard peak comparisons when no peak exists.

Verification

  • After splitting, all 65 existing manager-metrics, shared-metrics, access-key, and file-operation specs passed again on this isolated branch under Node 22.23.2.

  • Existing manager-metrics specs passed.

  • Controlled source checks verified ten concurrent reads sharing seven queries instead of seventy, failed-query retry, empty results, and unusual peak samples.

  • Targeted semantic TypeScript and formatting checks passed.

  • Patch isolation and git diff --check passed. Recombining all focused patches reproduces the reviewed source changes exactly.

  • No test/spec files were added or modified; controlled probe drivers are kept outside the repository.

Compatibility and remaining validation

  • The query-count result is a controlled local check, not a production throughput benchmark.
  • This PR deliberately excludes custom-ID serialization, which is reviewed separately. Both patches change distinct portions of the same file and can merge independently.

Full npm installation/build checks remain incomplete: npm 12 rejected existing lockfile Git dependencies (EALLOWGIT). Isolated registry-only tooling was used without disabling that safeguard.

Scope

This is one focused part of the reliability review, based directly on upstream master; it does not include the other review patches. No installed client, live VPN/DNS setting, or production service was changed by this patch.

Second review — 2026-08-27

Reuse the already-extracted bandwidth range instead of looping once and breaking. Use Date.now() directly for timestamps. Retain pending-query coalescing, failed-entry eviction and cache expiry behavior.

Controlled checks passed for seven shared queries across simultaneous dashboard reads, empty series, expiry, and failure retry. All 65 selected existing server specs and targeted TypeScript checks passed on this branch.

All touched files and nearby callers were reviewed again. Each focused patch was also checked in combination with the other seven patches for this repository. External probe drivers remain outside the repositories; no test/spec files were added or modified. Existing full-build and platform-validation limitations above still apply.

@OskarEichler
OskarEichler requested a review from fortuna as a code owner August 27, 2026 18:49
@greptile-apps

greptile-apps Bot commented Aug 27, 2026

Copy link
Copy Markdown

Greptile Summary

This PR replaces the dynamic Prometheus proxy with a typed promise cache that coalesces concurrent manager-metrics queries, removes failed entries for retry, and preserves five-minute result reuse.

  • Handles empty bandwidth query results without dereferencing a missing series.
  • Prevents peak selection from dereferencing a null peak for unusual non-finite samples.
  • Leaves the new cache lifecycle covered only by external probes rather than repository regression tests.

Confidence Score: 4/5

The PR appears safe to merge, with the non-blocking concern that its new cache lifecycle is not protected by repository regression tests.

The typed wrapper satisfies the complete PrometheusClient interface, concurrent calls share promises, rejected entries are retryable, and the null guards safely preserve default bandwidth values; only durable test coverage for the cache lifecycle is missing.

Files Needing Attention: src/shadowbox/server/manager_metrics.ts

Important Files Changed

Filename Overview
src/shadowbox/server/manager_metrics.ts Adds typed pending-query caching and defensive handling for empty or unusual Prometheus series; behavior appears sound, but the cache lifecycle lacks committed regression tests.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  R[Manager metrics request] --> P[Prune expired entries]
  P --> L{Cache entry exists?}
  L -->|Yes| A[Await shared promise]
  L -->|No| Q[Start Prometheus query]
  Q --> C[Cache pending promise]
  C --> A
  A --> S{Query succeeds?}
  S -->|Yes| T[Refresh timestamp and return result]
  S -->|No| E[Evict matching entry and rethrow]
Loading

Reviews (1): Last reviewed commit: "perf(server): coalesce metrics queries a..." | Re-trigger Greptile

Comment on lines +252 to +274
private async cachedQuery(
cacheId: string,
query: () => Promise<QueryResultData>
): Promise<QueryResultData> {
const cached = this.prometheusCache.get(cacheId);
if (cached) {
return cached.result;
}

return result;
};
},
});
// Cache the pending query too, so simultaneous dashboard requests share work.
const entry = {timestamp: Date.now(), result: query()};
this.prometheusCache.set(cacheId, entry);
try {
const result = await entry.result;
entry.timestamp = Date.now();
return result;
} catch (error) {
// A failed query must be retried; don't evict a newer entry with the same key.
if (this.prometheusCache.get(cacheId) === entry) {
this.prometheusCache.delete(cacheId);
}
throw error;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Cache lifecycle lacks tests

The new pending-promise reuse and rejection-eviction behavior has no repository regression coverage, so later changes can silently restore duplicate Prometheus queries, retain rejected promises, or break expiration semantics.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

@OskarEichler

Copy link
Copy Markdown
Author

Added coverage for pending-query sharing, successful-result reuse, rejection eviction, and retry. The focused manager metrics suite passes: 5 specs, 0 failures.

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