fix: keep candle retries read-only
Backend verify / commits (pull_request) Successful in 33s
Backend verify / security (pull_request) Successful in 1m28s
Backend verify / verify (pull_request) Failing after 4m12s

This commit is contained in:
2026-10-09 21:36:27 +03:00
parent 92c76e5d4b
commit 20fb2f6c6e
2 changed files with 8 additions and 3 deletions
@@ -29,6 +29,7 @@ import { timestamp } from './instrument-market';
const REPLACED_WINDOW_COUNT = 1; const REPLACED_WINDOW_COUNT = 1;
const NEXT_WINDOW_OFFSET = 1; const NEXT_WINDOW_OFFSET = 1;
const NO_CANDLE_GAPS = 0;
type CandleInput = { type CandleInput = {
instrumentType: 'bond' | 'share'; instrumentType: 'bond' | 'share';
@@ -114,7 +115,10 @@ export class CandleService {
? rangeFor(input, detail.instrument, now) ? rangeFor(input, detail.instrument, now)
: null; : null;
const saved = range ? await this.repository.read(input.uid, range) : null; const saved = range ? await this.repository.read(input.uid, range) : null;
if (!observe && !saved) { const hasCompleteRange = Boolean(
range && saved && candleGaps(range, saved.coverage, now).length === NO_CANDLE_GAPS,
);
if (!observe && (!saved || !hasCompleteRange)) {
await this.request(userId, revision, input, now); await this.request(userId, revision, input, now);
} }
const work = await this.repository.work(userId, revision, scope(input)); const work = await this.repository.work(userId, revision, scope(input));
+3 -2
View File
@@ -240,7 +240,8 @@ describe('atomic shared candle reconciliation (SQLite)', () => {
data: { fetchedAt: new Date(0) }, data: { fetchedAt: new Date(0) },
}); });
const stale = await reopened.read('owner', input, true); const stale = await reopened.read('owner', input, true);
expect(stale.meta.availability).toBe('complete'); expect(stale.meta.availability).toBe('available');
expect(stale.meta.completeness).toBe('complete');
expect(stale.meta.freshness).toBe('stale'); expect(stale.meta.freshness).toBe('stale');
expect(stale.meta.coverage?.missingRanges).toEqual([]); expect(stale.meta.coverage?.missingRanges).toEqual([]);
expect(stale.meta.coverage?.completeRanges.length).toBeGreaterThan(0); expect(stale.meta.coverage?.completeRanges.length).toBeGreaterThan(0);
@@ -302,7 +303,7 @@ describe('atomic shared candle reconciliation (SQLite)', () => {
expect(await prisma.tbankCandleCoverage.findMany()).toEqual(before); expect(await prisma.tbankCandleCoverage.findMany()).toEqual(before);
expect(await prisma.tbankCandle.count()).toBe(0); expect(await prisma.tbankCandle.count()).toBe(0);
const read = await service.read('owner', input, true); const read = await service.read('owner', input, true);
expect(read.meta.sync.state).toBe('failed'); expect(read.meta.lastAttempt.state).toBe('failed');
expect(read.data?.candles).toEqual([]); expect(read.data?.candles).toEqual([]);
}); });
it.each([ it.each([