Skip to content

Commit ede37f8

Browse files
authored
feat(server-core): Use LRU for OrchestratorStorage (#9425)
1 parent 128280a commit ede37f8

File tree

2 files changed

+19
-33
lines changed

2 files changed

+19
-33
lines changed

packages/cubejs-server-core/src/core/CompilerApi.js

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import crypto from 'crypto';
2-
import R from 'ramda';
32
import { createQuery, compile, queryClass, PreAggregations, QueryFactory } from '@cubejs-backend/schema-compiler';
43
import { v4 as uuidv4, parse as uuidParse } from 'uuid';
54
import { LRUCache } from 'lru-cache';
@@ -128,9 +127,9 @@ export class CompilerApi {
128127
async createQueryFactory(compilers) {
129128
const { cubeEvaluator } = compilers;
130129

131-
const cubeToQueryClass = R.fromPairs(
130+
const cubeToQueryClass = Object.fromEntries(
132131
await Promise.all(
133-
cubeEvaluator.cubeNames().map(async cube => {
132+
cubeEvaluator.cubeNames().map(async (cube) => {
134133
const dataSource = cubeEvaluator.cubeFromPath(cube).dataSource ?? 'default';
135134
const dbType = await this.getDbType(dataSource);
136135
const dialectClass = this.getDialectClass(dataSource, dbType);
@@ -146,7 +145,7 @@ export class CompilerApi {
146145
}
147146

148147
getDialectClass(dataSource = 'default', dbType) {
149-
return this.dialectClass && this.dialectClass({ dataSource, dbType });
148+
return this.dialectClass?.({ dataSource, dbType });
150149
}
151150

152151
async getSqlGenerator(query, dataSource) {
@@ -192,8 +191,8 @@ export class CompilerApi {
192191
external: sqlGenerator.externalPreAggregationQuery(),
193192
sql: sqlGenerator.buildSqlAndParams(exportAnnotatedSql),
194193
lambdaQueries: sqlGenerator.buildLambdaQuery(),
195-
timeDimensionAlias: sqlGenerator.timeDimensions[0] && sqlGenerator.timeDimensions[0].unescapedAliasName(),
196-
timeDimensionField: sqlGenerator.timeDimensions[0] && sqlGenerator.timeDimensions[0].dimension,
194+
timeDimensionAlias: sqlGenerator.timeDimensions[0]?.unescapedAliasName(),
195+
timeDimensionField: sqlGenerator.timeDimensions[0]?.dimension,
197196
order: sqlGenerator.order,
198197
cacheKeyQueries: sqlGenerator.cacheKeyQueries(),
199198
preAggregations: sqlGenerator.preAggregations.preAggregationsDescription(),
@@ -227,7 +226,7 @@ export class CompilerApi {
227226
}
228227

229228
roleMeetsConditions(evaluatedConditions) {
230-
if (evaluatedConditions && evaluatedConditions.length) {
229+
if (evaluatedConditions?.length) {
231230
return evaluatedConditions.reduce((a, b) => {
232231
if (typeof b !== 'boolean') {
233232
throw new Error(`Access policy condition must return boolean, got ${JSON.stringify(b)}`);
Lines changed: 13 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,16 @@
1+
import { LRUCache } from 'lru-cache';
12
import type { OrchestratorApi } from './OrchestratorApi';
23

34
export class OrchestratorStorage {
4-
protected readonly storage: Map<string, OrchestratorApi> = new Map();
5+
protected readonly storage: LRUCache<string, OrchestratorApi>;
6+
7+
public constructor(options: { compilerCacheSize?: number, maxCompilerCacheKeepAlive?: number, updateCompilerCacheKeepAlive?: boolean } = { compilerCacheSize: 100 }) {
8+
this.storage = new LRUCache<string, OrchestratorApi>({
9+
max: options.compilerCacheSize,
10+
ttl: options.maxCompilerCacheKeepAlive,
11+
updateAgeOnGet: options.updateCompilerCacheKeepAlive
12+
});
13+
}
514

615
public has(orchestratorId: string) {
716
return this.storage.has(orchestratorId);
@@ -20,37 +29,15 @@ export class OrchestratorStorage {
2029
}
2130

2231
public async testConnections() {
23-
const result = [];
24-
25-
// eslint-disable-next-line no-restricted-syntax
26-
for (const orchestratorApi of this.storage.values()) {
27-
result.push(orchestratorApi.testConnection());
28-
}
29-
30-
return Promise.all(result);
32+
return Promise.all([...this.storage.values()].map(api => api.testConnection()));
3133
}
3234

3335
public async testOrchestratorConnections() {
34-
const result = [];
35-
36-
// eslint-disable-next-line no-restricted-syntax
37-
for (const orchestratorApi of this.storage.values()) {
38-
result.push(orchestratorApi.testOrchestratorConnections());
39-
}
40-
41-
return Promise.all(result);
36+
return Promise.all([...this.storage.values()].map(api => api.testOrchestratorConnections()));
4237
}
4338

4439
public async releaseConnections() {
45-
const result = [];
46-
47-
// eslint-disable-next-line no-restricted-syntax
48-
for (const orchestratorApi of this.storage.values()) {
49-
result.push(orchestratorApi.release());
50-
}
51-
52-
await Promise.all(result);
53-
40+
await Promise.all([...this.storage.values()].map(api => api.release()));
5441
this.storage.clear();
5542
}
5643
}

0 commit comments

Comments
 (0)