Repository navigation
fix(sse): remove race condition in cache metrics tracking - #758
diegosouzapw merged 1 commit into
Conversation
- Remove in-memory metrics tracking (currentMetrics, trackCacheMetrics, updateCacheMetrics) - Cache metrics now computed on-the-fly from usage_history table (single source of truth) - Fixes CRITICAL issue from code review: concurrent requests overwriting metrics - Fixes WARNING: duplicate metric tracking logic in streaming/non-streaming paths Ref: PR cheaper-inference#752 (merged before this fix was included)
There was a problem hiding this comment.
Code Review
This pull request removes cache metrics tracking and persistence from the handleChatCore function and adds usage saving for streaming responses. The review feedback suggests cleaning up resulting dead code in utility files and refactoring duplicated usage-saving logic into a helper function to improve maintainability.
| type CacheControlMetrics, | ||
| } from "../utils/cacheControlPolicy.ts"; | ||
| import { getCacheMetrics, updateCacheMetrics } from "@/lib/db/settings.ts"; | ||
| import { shouldPreserveCacheControl, recordCacheHit } from "../utils/cacheControlPolicy.ts"; |
There was a problem hiding this comment.
| saveRequestUsage({ | ||
| provider: provider || "unknown", | ||
| model: model || "unknown", | ||
| tokens: streamUsage, | ||
| status: String(streamStatus || 200), | ||
| success: streamStatus === 200, | ||
| latencyMs: Date.now() - startTime, | ||
| timeToFirstTokenMs: ttft, | ||
| errorCode: null, | ||
| timestamp: new Date().toISOString(), | ||
| connectionId: connectionId || undefined, | ||
| apiKeyId: apiKeyInfo?.id || undefined, | ||
| apiKeyName: apiKeyInfo?.name || undefined, | ||
| }).catch((err) => { | ||
| console.error("Failed to save usage stats:", err.message); | ||
| }); |
There was a problem hiding this comment.
This saveRequestUsage call is very similar to the one for non-streaming responses around line 1450. To improve maintainability and reduce code duplication, consider refactoring the common logic into a helper function.
For example, a helper could create the base object with common properties like provider, model, timestamp, etc., which can then be spread and extended in both call sites.
function getBaseUsageData() {
return {
provider: provider || "unknown",
model: model || "unknown",
errorCode: null,
timestamp: new Date().toISOString(),
connectionId: connectionId || undefined,
apiKeyId: apiKeyInfo?.id || undefined,
apiKeyName: apiKeyInfo?.name || undefined,
};
}
Code Review SummaryStatus: 1 CRITICAL Issue Found | Recommendation: Revert or hotfix immediately
CRITICAL Issues
Issue Details
The PR removes the // Line 1558 - still references removed symbols
updateCacheMetrics(currentMetrics).catch((err) => {
Impact: All non-streaming chat completions that reach line 1558 will throw a Fix required: Either:
Since Files Reviewed (1 file)
Additional NotesThe streaming path also had a similar |
89bd31c
into
cheaper-inference:release/v3.2.8
|
Thank you for the contribution! This fix has been merged into release v3.2.8. |
* chore(release): v3.2.8 — Docker auto-update UI and cache analytics fixes * fix(sse): remove race condition in cache metrics tracking (#758) - Remove in-memory metrics tracking (currentMetrics, trackCacheMetrics, updateCacheMetrics) - Cache metrics now computed on-the-fly from usage_history table (single source of truth) - Fixes CRITICAL issue from code review: concurrent requests overwriting metrics - Fixes WARNING: duplicate metric tracking logic in streaming/non-streaming paths Ref: PR #752 (merged before this fix was included) * fix: handle allRateLimited credentials & forward extra body keys in embeddings/images routes (#757) * fix: handle allRateLimited credentials in embeddings and images routes When getProviderCredentials() returns an allRateLimited object (truthy, but without apiKey/accessToken), the embeddings and images routes incorrectly passed it to handlers as valid credentials. The handlers then sent upstream requests without Authorization headers, causing 401 errors from providers (e.g. NVIDIA NIM). This only manifested under concurrent requests: a chat/completions call could trigger rate limiting on a provider account, and a simultaneous embeddings request would receive the allRateLimited sentinel — but treat it as valid credentials. The chat pipeline already handled this case correctly. This commit adds the same allRateLimited guard to all affected routes: - POST /v1/embeddings - POST /v1/providers/{provider}/embeddings - POST /v1/images/generations - POST /v1/providers/{provider}/images/generations Also adds a defense-in-depth guard in the embeddings handler itself: if no auth token is available for a non-local provider, return 401 immediately instead of sending an unauthenticated request upstream. Made-with: Cursor * fix(embeddings): forward extra body keys to upstream providers The embeddings handler only forwarded model, input, dimensions, and encoding_format to upstream providers, silently dropping any additional fields. This broke asymmetric embedding APIs (e.g. NVIDIA NIM nv-embedqa-e5-v5) that require input_type, and other providers expecting user or truncate parameters. Add a KNOWN_FIELDS exclusion set and forward all unrecognized body keys to the upstream request, matching the passthrough pattern used by the chat pipeline's DefaultExecutor.transformRequest(). Made-with: Cursor * fix(auth): redirect and unconditional 401 on disabled requireLogin + fix test cases * fix(build): remove legacy proxy.ts causing Next.js build collision * fix(build): revert middleware.ts rename to proxy.ts because of Next.js Edge constraints --------- Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com> Co-authored-by: tombii <tombii@users.noreply.github.com> Co-authored-by: Gorchakov-Pressure <117600961+Gorchakov-Pressure@users.noreply.github.com>
…r-inference#755) * chore(release): v3.2.8 — Docker auto-update UI and cache analytics fixes * fix(sse): remove race condition in cache metrics tracking (cheaper-inference#758) - Remove in-memory metrics tracking (currentMetrics, trackCacheMetrics, updateCacheMetrics) - Cache metrics now computed on-the-fly from usage_history table (single source of truth) - Fixes CRITICAL issue from code review: concurrent requests overwriting metrics - Fixes WARNING: duplicate metric tracking logic in streaming/non-streaming paths Ref: PR cheaper-inference#752 (merged before this fix was included) * fix: handle allRateLimited credentials & forward extra body keys in embeddings/images routes (cheaper-inference#757) * fix: handle allRateLimited credentials in embeddings and images routes When getProviderCredentials() returns an allRateLimited object (truthy, but without apiKey/accessToken), the embeddings and images routes incorrectly passed it to handlers as valid credentials. The handlers then sent upstream requests without Authorization headers, causing 401 errors from providers (e.g. NVIDIA NIM). This only manifested under concurrent requests: a chat/completions call could trigger rate limiting on a provider account, and a simultaneous embeddings request would receive the allRateLimited sentinel — but treat it as valid credentials. The chat pipeline already handled this case correctly. This commit adds the same allRateLimited guard to all affected routes: - POST /v1/embeddings - POST /v1/providers/{provider}/embeddings - POST /v1/images/generations - POST /v1/providers/{provider}/images/generations Also adds a defense-in-depth guard in the embeddings handler itself: if no auth token is available for a non-local provider, return 401 immediately instead of sending an unauthenticated request upstream. Made-with: Cursor * fix(embeddings): forward extra body keys to upstream providers The embeddings handler only forwarded model, input, dimensions, and encoding_format to upstream providers, silently dropping any additional fields. This broke asymmetric embedding APIs (e.g. NVIDIA NIM nv-embedqa-e5-v5) that require input_type, and other providers expecting user or truncate parameters. Add a KNOWN_FIELDS exclusion set and forward all unrecognized body keys to the upstream request, matching the passthrough pattern used by the chat pipeline's DefaultExecutor.transformRequest(). Made-with: Cursor * fix(auth): redirect and unconditional 401 on disabled requireLogin + fix test cases * fix(build): remove legacy proxy.ts causing Next.js build collision * fix(build): revert middleware.ts rename to proxy.ts because of Next.js Edge constraints --------- Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com> Co-authored-by: tombii <tombii@users.noreply.github.com> Co-authored-by: Gorchakov-Pressure <117600961+Gorchakov-Pressure@users.noreply.github.com>
…r-inference#755) * chore(release): v3.2.8 — Docker auto-update UI and cache analytics fixes * fix(sse): remove race condition in cache metrics tracking (cheaper-inference#758) - Remove in-memory metrics tracking (currentMetrics, trackCacheMetrics, updateCacheMetrics) - Cache metrics now computed on-the-fly from usage_history table (single source of truth) - Fixes CRITICAL issue from code review: concurrent requests overwriting metrics - Fixes WARNING: duplicate metric tracking logic in streaming/non-streaming paths Ref: PR cheaper-inference#752 (merged before this fix was included) * fix: handle allRateLimited credentials & forward extra body keys in embeddings/images routes (cheaper-inference#757) * fix: handle allRateLimited credentials in embeddings and images routes When getProviderCredentials() returns an allRateLimited object (truthy, but without apiKey/accessToken), the embeddings and images routes incorrectly passed it to handlers as valid credentials. The handlers then sent upstream requests without Authorization headers, causing 401 errors from providers (e.g. NVIDIA NIM). This only manifested under concurrent requests: a chat/completions call could trigger rate limiting on a provider account, and a simultaneous embeddings request would receive the allRateLimited sentinel — but treat it as valid credentials. The chat pipeline already handled this case correctly. This commit adds the same allRateLimited guard to all affected routes: - POST /v1/embeddings - POST /v1/providers/{provider}/embeddings - POST /v1/images/generations - POST /v1/providers/{provider}/images/generations Also adds a defense-in-depth guard in the embeddings handler itself: if no auth token is available for a non-local provider, return 401 immediately instead of sending an unauthenticated request upstream. Made-with: Cursor * fix(embeddings): forward extra body keys to upstream providers The embeddings handler only forwarded model, input, dimensions, and encoding_format to upstream providers, silently dropping any additional fields. This broke asymmetric embedding APIs (e.g. NVIDIA NIM nv-embedqa-e5-v5) that require input_type, and other providers expecting user or truncate parameters. Add a KNOWN_FIELDS exclusion set and forward all unrecognized body keys to the upstream request, matching the passthrough pattern used by the chat pipeline's DefaultExecutor.transformRequest(). Made-with: Cursor * fix(auth): redirect and unconditional 401 on disabled requireLogin + fix test cases * fix(build): remove legacy proxy.ts causing Next.js build collision * fix(build): revert middleware.ts rename to proxy.ts because of Next.js Edge constraints --------- Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com> Co-authored-by: tombii <tombii@users.noreply.github.com> Co-authored-by: Gorchakov-Pressure <117600961+Gorchakov-Pressure@users.noreply.github.com>
Summary
Follow-up fix for PR #752 which was merged before this critical fix was included.
Changes
Addresses Code Review Issues
From the original PR review bots:
Testing
All cache-related unit tests pass. Two pre-existing test failures unrelated to this change: