short circuit getCandles if a negative cache exists
This commit is contained in:
parent
a15b9cf471
commit
9699bed480
1 changed files with 37 additions and 0 deletions
|
|
@ -826,6 +826,17 @@ pub const DataService = struct {
|
||||||
/// `opts.force_refresh = true` -> treats cache as stale and fetches.
|
/// `opts.force_refresh = true` -> treats cache as stale and fetches.
|
||||||
pub fn getCandles(self: *DataService, symbol: []const u8, opts: FetchOptions) DataError!FetchResult(Candle) {
|
pub fn getCandles(self: *DataService, symbol: []const u8, opts: FetchOptions) DataError!FetchResult(Candle) {
|
||||||
var s = self.store();
|
var s = self.store();
|
||||||
|
|
||||||
|
// Negative cache: this symbol is known to have no candle data on
|
||||||
|
// any provider (e.g. crypto like DOGE-USD that Tiingo can't
|
||||||
|
// serve). The marker lives in candles_daily.srf - written by the
|
||||||
|
// permanent-NotFound path below, or synced verbatim from a
|
||||||
|
// ZFIN_SERVER. Bail before any server sync or provider fetch so
|
||||||
|
// repeated calls don't re-hit the network every invocation.
|
||||||
|
// --refresh-data=force (force_refresh) bypasses this to retry.
|
||||||
|
if (!opts.force_refresh and s.isNegative(symbol, .candles_daily))
|
||||||
|
return DataError.FetchFailed;
|
||||||
|
|
||||||
const today = fmt.todayDate(self.io);
|
const today = fmt.todayDate(self.io);
|
||||||
|
|
||||||
// wall-clock required: candle-meta freshness uses a market-aware
|
// wall-clock required: candle-meta freshness uses a market-aware
|
||||||
|
|
@ -3340,6 +3351,32 @@ test "loadLiveQuotes: empty symbol list returns empty without touching the netwo
|
||||||
try std.testing.expectEqual(@as(usize, 0), prices.count());
|
try std.testing.expectEqual(@as(usize, 0), prices.count());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "getCandles: negative candle cache short-circuits without touching the network" {
|
||||||
|
const allocator = std.testing.allocator;
|
||||||
|
const io = std.testing.io;
|
||||||
|
var tmp = std.testing.tmpDir(.{});
|
||||||
|
defer tmp.cleanup();
|
||||||
|
const dir_path = try tmp.dir.realPathFileAlloc(io, ".", allocator);
|
||||||
|
defer allocator.free(dir_path);
|
||||||
|
|
||||||
|
var svc = DataService.init(io, allocator, .{ .cache_dir = dir_path });
|
||||||
|
defer svc.deinit();
|
||||||
|
|
||||||
|
// Seed a negative candle entry: this symbol has no candle data on
|
||||||
|
// any provider (the crypto / defunct-ticker case). The marker lives
|
||||||
|
// in candles_daily.srf; candles_meta.srf is never created.
|
||||||
|
var s = svc.store();
|
||||||
|
try s.ensureSymbolDir("DOGE-USD");
|
||||||
|
s.writeNegative("DOGE-USD", .candles_daily);
|
||||||
|
|
||||||
|
// Any server sync or provider fetch would trip this panic guard.
|
||||||
|
svc.panic_on_network_attempt = true;
|
||||||
|
|
||||||
|
// getCandles must recognize the negative entry and fail fast, with
|
||||||
|
// no network round-trip (no panic).
|
||||||
|
try std.testing.expectError(DataError.FetchFailed, svc.getCandles("DOGE-USD", .{}));
|
||||||
|
}
|
||||||
|
|
||||||
test "DataService store helper creates valid store" {
|
test "DataService store helper creates valid store" {
|
||||||
const allocator = std.testing.allocator;
|
const allocator = std.testing.allocator;
|
||||||
const config = Config{
|
const config = Config{
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue