mirror of
https://github.com/koala73/worldmonitor.git
synced 2026-04-25 17:14:57 +02:00
fix(gold-intelligence): read correct Redis key and data shape (#3013)
* fix(gold-intelligence): read correct Redis key and data shape
Handler read 'market:commodity-quotes:v1' (doesn't exist). Actual seeded
key is 'market:commodities-bootstrap:v1'. Also expected raw array but
seeder writes { quotes: [...] }. Both bugs caused permanent "Gold data
unavailable" in the panel.
* fix(market): return unavailable when GC=F quote is missing from commodity snapshot
This commit is contained in:
@@ -7,7 +7,7 @@ import type {
|
||||
} from '../../../../src/generated/server/worldmonitor/market/v1/service_server';
|
||||
import { getCachedJson } from '../../../_shared/redis';
|
||||
|
||||
const COMMODITY_KEY = 'market:commodity-quotes:v1';
|
||||
const COMMODITY_KEY = 'market:commodities-bootstrap:v1';
|
||||
const COT_KEY = 'market:cot:v1';
|
||||
|
||||
interface RawQuote {
|
||||
@@ -44,18 +44,22 @@ export async function getGoldIntelligence(
|
||||
_req: GetGoldIntelligenceRequest,
|
||||
): Promise<GetGoldIntelligenceResponse> {
|
||||
try {
|
||||
const [rawQuotes, rawCot] = await Promise.all([
|
||||
getCachedJson(COMMODITY_KEY, true) as Promise<RawQuote[] | null>,
|
||||
const [rawPayload, rawCot] = await Promise.all([
|
||||
getCachedJson(COMMODITY_KEY, true) as Promise<{ quotes?: RawQuote[] } | null>,
|
||||
getCachedJson(COT_KEY, true) as Promise<{ instruments?: RawCotInstrument[]; reportDate?: string } | null>,
|
||||
]);
|
||||
|
||||
if (!rawQuotes || !Array.isArray(rawQuotes)) {
|
||||
const rawQuotes = rawPayload?.quotes;
|
||||
if (!rawQuotes || !Array.isArray(rawQuotes) || rawQuotes.length === 0) {
|
||||
return { goldPrice: 0, goldChangePct: 0, goldSparkline: [], silverPrice: 0, platinumPrice: 0, palladiumPrice: 0, crossCurrencyPrices: [], updatedAt: '', unavailable: true };
|
||||
}
|
||||
|
||||
const quoteMap = new Map(rawQuotes.map(q => [q.symbol, q]));
|
||||
|
||||
const gold = quoteMap.get('GC=F');
|
||||
if (!gold) {
|
||||
return { goldPrice: 0, goldChangePct: 0, goldSparkline: [], silverPrice: 0, platinumPrice: 0, palladiumPrice: 0, crossCurrencyPrices: [], updatedAt: '', unavailable: true };
|
||||
}
|
||||
const silver = quoteMap.get('SI=F');
|
||||
const platinum = quoteMap.get('PL=F');
|
||||
const palladium = quoteMap.get('PA=F');
|
||||
|
||||
@@ -97,6 +97,26 @@ describe('Gold Intelligence', () => {
|
||||
assert.ok(Math.abs(premium - ((3200 - 950) / 950) * 100) < 0.01);
|
||||
});
|
||||
|
||||
it('returns unavailable when GC=F is missing from commodity snapshot', () => {
|
||||
const quotes = [
|
||||
{ symbol: 'SI=F', price: 35 },
|
||||
{ symbol: 'PL=F', price: 950 },
|
||||
{ symbol: 'PA=F', price: 1020 },
|
||||
{ symbol: 'EURUSD=X', price: 1.08 },
|
||||
];
|
||||
const quoteMap = new Map(quotes.map(q => [q.symbol, q]));
|
||||
const gold = quoteMap.get('GC=F');
|
||||
assert.strictEqual(gold, undefined);
|
||||
|
||||
const goldPrice = gold?.price ?? 0;
|
||||
assert.strictEqual(goldPrice, 0);
|
||||
|
||||
const ratio = computeGoldSilverRatio(goldPrice, 35);
|
||||
assert.strictEqual(ratio, null);
|
||||
const cross = computeCrossCurrency(goldPrice, quotes);
|
||||
assert.strictEqual(cross.length, 0);
|
||||
});
|
||||
|
||||
it('partial availability: price works when cot is null, and vice versa', () => {
|
||||
const goldPrice = 3200;
|
||||
const silverPrice = 35;
|
||||
|
||||
Reference in New Issue
Block a user