Skip to content

Commit 19d46af

Browse files
perf(ender:candles): precompute strings, simpler getCandle (#3317)
1 parent 728120b commit 19d46af

File tree

2 files changed

+36
-38
lines changed

2 files changed

+36
-38
lines changed

indexer/services/ender/src/caches/candle-cache.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,7 @@ export function getCandle(
4545
ticker: string,
4646
resolution: CandleResolution,
4747
): CandleFromDatabase | undefined {
48-
if (ticker in candlesMap && resolution in candlesMap[ticker]) {
49-
return candlesMap[ticker][resolution];
50-
}
51-
52-
return undefined;
48+
return candlesMap[ticker]?.[resolution];
5349
}
5450

5551
export function updateCandleCacheWithCandle(candle: CandleFromDatabase): void {

indexer/services/ender/src/lib/candles-generator.ts

Lines changed: 35 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ export class CandlesGenerator {
5454
txId: number;
5555
writeOptions: Options;
5656
resolutionStartTimes: Map<CandleResolution, DateTime>;
57+
resolutionStartTimesISO: Map<CandleResolution, string>;
5758

5859
constructor(
5960
kafkaPublisher: KafkaPublisher,
@@ -71,6 +72,13 @@ export class CandlesGenerator {
7172
CandlesGenerator.calculateNormalizedCandleStartTime(this.blockTimestamp, resolution),
7273
];
7374
}));
75+
this.resolutionStartTimesISO = new Map(
76+
Object.values(CandleResolution).map((resolution: CandleResolution) => {
77+
return [
78+
resolution,
79+
this.resolutionStartTimes.get(resolution)!.toISO(),
80+
];
81+
}));
7482
}
7583

7684
/**
@@ -83,24 +91,16 @@ export class CandlesGenerator {
8391
*/
8492
public async updateCandles(): Promise<CandleFromDatabase[]> {
8593
const start: number = Date.now();
86-
// 1. Sort trade messages by order in the block
87-
this.kafkaPublisher.sortEvents(this.kafkaPublisher.tradeMessages);
88-
89-
// 2. Generate BlockCandleUpdatesMap
90-
const blockCandleUpdatesMap: BlockCandleUpdatesMap = this.generateBlockCandleUpdatesMap();
91-
92-
// 3. Update and Create Candles in postgres
93-
const candles: CandleFromDatabase[] = await this.createOrUpdatePostgresCandles(
94-
blockCandleUpdatesMap,
95-
);
9694

97-
// 4. Add Candle kafka messages to KafkaPublisher
95+
this.kafkaPublisher.sortEvents(this.kafkaPublisher.tradeMessages);
96+
const candles: CandleFromDatabase[] = await this.createOrUpdatePostgresCandles();
9897
this.addCandleKafkaMessages(candles);
9998

10099
stats.timing(
101100
`${config.SERVICE_NAME}.update_candles.timing`,
102101
Date.now() - start,
103102
);
103+
104104
return candles;
105105
}
106106

@@ -173,17 +173,23 @@ export class CandlesGenerator {
173173
};
174174
}
175175

176-
private async createOrUpdatePostgresCandles(
177-
blockCandleUpdatesMap: BlockCandleUpdatesMap,
178-
): Promise<CandleFromDatabase[]> {
176+
private async createOrUpdatePostgresCandles(): Promise<CandleFromDatabase[]> {
179177
const start: number = Date.now();
178+
const blockCandleUpdatesMap: BlockCandleUpdatesMap = this.generateBlockCandleUpdatesMap();
180179
const promises: Promise<CandleFromDatabase | undefined>[] = [];
181180

182-
const openInterestMap: OpenInterestMap = await this.getOpenInterestMap();
181+
const perpetualMarkets: PerpetualMarketFromDatabase[] = Object.values(
182+
perpetualMarketRefresher.getPerpetualMarketsMap(),
183+
);
184+
const perpetualMarketTickers: string[] = _.map(
185+
perpetualMarkets,
186+
PerpetualMarketColumns.ticker,
187+
);
188+
const openInterestMap: OpenInterestMap = await this.getOpenInterestMap(perpetualMarketTickers);
183189
const orderbookMidPriceMap = getOrderbookMidPriceMap();
184190

185191
_.forEach(
186-
Object.values(perpetualMarketRefresher.getPerpetualMarketsMap()),
192+
perpetualMarkets,
187193
(perpetualMarket: PerpetualMarketFromDatabase) => {
188194
const blockCandleUpdate: BlockCandleUpdate | undefined = blockCandleUpdatesMap[
189195
perpetualMarket.ticker
@@ -198,7 +204,7 @@ export class CandlesGenerator {
198204
resolution,
199205
openInterestMap,
200206
orderbookMidPriceMap[perpetualMarket.ticker],
201-
this.resolutionStartTimes.get(resolution)!,
207+
this.resolutionStartTimesISO.get(resolution)!,
202208
));
203209
},
204210
);
@@ -237,7 +243,7 @@ export class CandlesGenerator {
237243
resolution: CandleResolution,
238244
openInterestMap: OpenInterestMap,
239245
orderbookMidPrice: OrderbookMidPrice,
240-
currentStartTime: DateTime,
246+
currentStartTimeISO: string,
241247
): Promise<CandleFromDatabase | undefined>[] {
242248

243249
const existingCandle: CandleFromDatabase | undefined = getCandle(
@@ -252,7 +258,7 @@ export class CandlesGenerator {
252258
}
253259
// - Candle doesn't exist & there is a block update - create candle
254260
return [this.createCandleInPostgres(
255-
currentStartTime,
261+
currentStartTimeISO,
256262
blockCandleUpdate,
257263
ticker,
258264
resolution,
@@ -261,7 +267,7 @@ export class CandlesGenerator {
261267
)];
262268
}
263269

264-
const sameStartTime: boolean = existingCandle.startedAt === currentStartTime.toISO();
270+
const sameStartTime: boolean = existingCandle.startedAt === currentStartTimeISO;
265271
if (!sameStartTime) {
266272
// - Candle exists & !sameStartTime & there is a block update - create candle
267273
// update previous candle orderbookMidPriceClose
@@ -273,7 +279,7 @@ export class CandlesGenerator {
273279

274280
if (blockCandleUpdate !== undefined) {
275281
return [previousCandleUpdate, this.createCandleInPostgres(
276-
currentStartTime,
282+
currentStartTimeISO,
277283
blockCandleUpdate,
278284
ticker,
279285
resolution,
@@ -284,7 +290,7 @@ export class CandlesGenerator {
284290
// - Candle exists & !sameStartTime & there is no block update - create empty candle
285291
// update previous candle orderbookMidPriceClose/Open
286292
return [previousCandleUpdate, this.createEmptyCandleInPostgres(
287-
currentStartTime,
293+
currentStartTimeISO,
288294
ticker,
289295
resolution,
290296
openInterestMap,
@@ -308,18 +314,14 @@ export class CandlesGenerator {
308314
* therefore require open interest to be calculated.
309315
*/
310316
// eslint-disable-next-line @typescript-eslint/require-await
311-
private async getOpenInterestMap(): Promise<OpenInterestMap> {
317+
private async getOpenInterestMap(perpetualMarketTickers: string[]): Promise<OpenInterestMap> {
312318
const start: number = Date.now();
313-
const allTickers: string[] = _.map(
314-
Object.values(perpetualMarketRefresher.getPerpetualMarketsMap()),
315-
PerpetualMarketColumns.ticker,
316-
);
317319

318-
const tickersToFetch: string[] = _.filter(allTickers, (ticker: string) => {
320+
const tickersToFetch: string[] = _.filter(perpetualMarketTickers, (ticker: string) => {
319321
return _.some(
320322
Object.values(CandleResolution),
321323
(resolution: CandleResolution) => {
322-
const startedAtISOString: string = this.resolutionStartTimes.get(resolution)!.toISO();
324+
const startedAtISOString: string = this.resolutionStartTimesISO.get(resolution)!;
323325
const existingCandle: CandleFromDatabase | undefined = getCandle(ticker, resolution);
324326
return existingCandle === undefined || existingCandle.startedAt !== startedAtISOString;
325327
},
@@ -370,15 +372,15 @@ export class CandlesGenerator {
370372

371373
// eslint-disable-next-line @typescript-eslint/require-await
372374
private async createCandleInPostgres(
373-
startedAt: DateTime,
375+
startedAtISO: string,
374376
blockCandleUpdate: BlockCandleUpdate,
375377
ticker: string,
376378
resolution: CandleResolution,
377379
openInterestMap: OpenInterestMap,
378380
orderbookMidPrice: OrderbookMidPrice,
379381
): Promise<CandleFromDatabase> {
380382
const candle: CandleCreateObject = {
381-
startedAt: startedAt.toISO(),
383+
startedAt: startedAtISO,
382384
ticker,
383385
resolution,
384386
low: blockCandleUpdate.low,
@@ -402,15 +404,15 @@ export class CandlesGenerator {
402404
*/
403405
// eslint-disable-next-line @typescript-eslint/require-await
404406
private async createEmptyCandleInPostgres(
405-
startedAt: DateTime,
407+
startedAtISO: string,
406408
ticker: string,
407409
resolution: CandleResolution,
408410
openInterestMap: OpenInterestMap,
409411
existingCandle: CandleFromDatabase,
410412
orderbookMidPrice: OrderbookMidPrice,
411413
): Promise<CandleFromDatabase> {
412414
const candle: CandleCreateObject = {
413-
startedAt: startedAt.toISO(),
415+
startedAt: startedAtISO,
414416
ticker,
415417
resolution,
416418
low: existingCandle.close,

0 commit comments

Comments
 (0)