Skip to content

Commit 704eb5e

Browse files
authored
chore: update datasource schema read methods (cube-js#9831)
* dev * fix * upd
1 parent e20f6c0 commit 704eb5e

File tree

2 files changed

+44
-52
lines changed

2 files changed

+44
-52
lines changed

packages/cubejs-query-orchestrator/src/orchestrator/QueryOrchestrator.ts

Lines changed: 11 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,7 @@ export class QueryOrchestrator {
446446
// TODO (@MikeNitsenko): Metadata queries need object params like [{ schema, table }]
447447
// but QueryWithParams expects string[]. This forces JSON.stringify workaround.
448448
[JSON.stringify(params)],
449-
{ external: false, renewalThreshold: 24 * 60 * 60 }
449+
{ external: false }
450450
];
451451
}
452452

@@ -456,40 +456,31 @@ export class QueryOrchestrator {
456456
dataSource: string = 'default',
457457
options: {
458458
requestId?: string;
459-
forceRefresh?: boolean;
460-
renewalThreshold?: number;
459+
syncJobId?: string;
461460
expiration?: number;
462461
} = {}
463462
): Promise<T> {
464463
const {
465464
requestId,
466-
forceRefresh = false,
467-
renewalThreshold = 24 * 60 * 60,
468-
expiration = 7 * 24 * 60 * 60,
465+
syncJobId,
466+
expiration = 30 * 24 * 60 * 60,
469467
} = options;
470468

471469
const metadataQuery = this.createMetadataQuery(operation, params);
472-
const cacheKey: CacheKey = [metadataQuery, dataSource];
473-
474-
const renewalKey = forceRefresh ? undefined : [
475-
`METADATA_RENEWAL:${operation}`,
476-
dataSource,
477-
Math.floor(Date.now() / (renewalThreshold * 1000))
478-
];
470+
const cacheKey: CacheKey = syncJobId
471+
? [metadataQuery, dataSource, syncJobId]
472+
: [metadataQuery, dataSource];
479473

480474
return this.queryCache.cacheQueryResult(
481475
metadataQuery,
482476
[],
483477
cacheKey,
484478
expiration,
485479
{
486-
renewalThreshold,
487-
renewalKey,
488-
forceNoCache: forceRefresh,
489480
requestId,
490481
dataSource,
482+
forceNoCache: !syncJobId,
491483
useInMemory: true,
492-
waitForRenew: true,
493484
}
494485
);
495486
}
@@ -501,8 +492,7 @@ export class QueryOrchestrator {
501492
dataSource: string = 'default',
502493
options: {
503494
requestId?: string;
504-
forceRefresh?: boolean;
505-
renewalThreshold?: number;
495+
syncJobId?: string;
506496
expiration?: number;
507497
} = {}
508498
): Promise<QuerySchemasResult[]> {
@@ -522,8 +512,7 @@ export class QueryOrchestrator {
522512
dataSource: string = 'default',
523513
options: {
524514
requestId?: string;
525-
forceRefresh?: boolean;
526-
renewalThreshold?: number;
515+
syncJobId?: string;
527516
expiration?: number;
528517
} = {}
529518
): Promise<QueryTablesResult[]> {
@@ -543,8 +532,7 @@ export class QueryOrchestrator {
543532
dataSource: string = 'default',
544533
options: {
545534
requestId?: string;
546-
forceRefresh?: boolean;
547-
renewalThreshold?: number;
535+
syncJobId?: string;
548536
expiration?: number;
549537
} = {}
550538
): Promise<QueryColumnsResult[]> {

packages/cubejs-query-orchestrator/test/unit/QueryOrchestrator.test.js

Lines changed: 33 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1955,30 +1955,34 @@ describe('QueryOrchestrator', () => {
19551955
]);
19561956
});
19571957

1958-
test('should use cache on second call', async () => {
1959-
// First call
1960-
await metadataOrchestrator.queryDataSourceSchemas();
1961-
// Second call should use cache
1962-
const result = await metadataOrchestrator.queryDataSourceSchemas();
1958+
test('should use cache when syncJobId is provided', async () => {
1959+
// First call with syncJobId
1960+
await metadataOrchestrator.queryDataSourceSchemas('default', { syncJobId: 'job-123' });
1961+
1962+
// Clear the mock calls
1963+
metadataMockDriver.getSchemas.mockClear();
1964+
1965+
// Second call with same syncJobId should use cache
1966+
const result = await metadataOrchestrator.queryDataSourceSchemas('default', { syncJobId: 'job-123' });
19631967

19641968
expect(result).toEqual([
19651969
{ schema_name: 'public' },
19661970
{ schema_name: 'analytics' },
19671971
{ schema_name: 'staging' }
19681972
]);
1973+
1974+
// Verify driver wasn't called again
1975+
expect(metadataMockDriver.getSchemas).not.toHaveBeenCalled();
19691976
});
19701977

1971-
test('should force refresh when requested', async () => {
1978+
test('should refresh when syncJobId is not provided', async () => {
19721979
// First call
19731980
await metadataOrchestrator.queryDataSourceSchemas();
1974-
// Second call with forceRefresh
1975-
const result = await metadataOrchestrator.queryDataSourceSchemas('default', { forceRefresh: true });
1981+
// Second call without syncJobId should refresh
1982+
await metadataOrchestrator.queryDataSourceSchemas();
19761983

1977-
expect(result).toEqual([
1978-
{ schema_name: 'public' },
1979-
{ schema_name: 'analytics' },
1980-
{ schema_name: 'staging' }
1981-
]);
1984+
// Driver should be called twice
1985+
expect(metadataMockDriver.getSchemas).toHaveBeenCalledTimes(2);
19821986
});
19831987

19841988
test('should pass requestId option', async () => {
@@ -2008,11 +2012,11 @@ describe('QueryOrchestrator', () => {
20082012
expect(metadataMockDriver.getTablesForSpecificSchemas).toHaveBeenCalledWith(schemas);
20092013
});
20102014

2011-
test('should cache results based on schema list', async () => {
2015+
test('should use cache when syncJobId is provided', async () => {
20122016
const schemas = [{ schema_name: 'public' }];
20132017

2014-
// First call - will execute and store in cache
2015-
await metadataOrchestrator.queryTablesForSchemas(schemas);
2018+
// First call with syncJobId - will execute and store in cache
2019+
await metadataOrchestrator.queryTablesForSchemas(schemas, 'default', { syncJobId: 'job-123' });
20162020

20172021
// Add a delay to ensure the first query has completed and cached its result
20182022
await new Promise(resolve => setTimeout(resolve, 100));
@@ -2024,8 +2028,8 @@ describe('QueryOrchestrator', () => {
20242028
// Our hash function should handle this correctly
20252029
const schemas2 = [{ schema_name: 'public' }];
20262030

2027-
// Second call should use cache
2028-
const result = await metadataOrchestrator.queryTablesForSchemas(schemas2);
2031+
// Second call with same syncJobId should use cache
2032+
const result = await metadataOrchestrator.queryTablesForSchemas(schemas2, 'default', { syncJobId: 'job-123' });
20292033

20302034
expect(result).toEqual([
20312035
{ schema_name: 'public', table_name: 'users' },
@@ -2044,11 +2048,11 @@ describe('QueryOrchestrator', () => {
20442048
expect(metadataMockDriver.getTablesForSpecificSchemas).toHaveBeenCalledWith([]);
20452049
});
20462050

2047-
test('should force refresh when requested', async () => {
2051+
test('should refresh when syncJobId is not provided', async () => {
20482052
const schemas = [{ schema_name: 'public' }];
20492053

20502054
await metadataOrchestrator.queryTablesForSchemas(schemas);
2051-
await metadataOrchestrator.queryTablesForSchemas(schemas, 'default', { forceRefresh: true });
2055+
await metadataOrchestrator.queryTablesForSchemas(schemas);
20522056

20532057
expect(metadataMockDriver.getTablesForSpecificSchemas).toHaveBeenCalledTimes(2);
20542058
});
@@ -2111,11 +2115,11 @@ describe('QueryOrchestrator', () => {
21112115
expect(metadataMockDriver.getColumnsForSpecificTables).toHaveBeenCalledWith(tables);
21122116
});
21132117

2114-
test('should cache results based on table list', async () => {
2118+
test('should use cache when syncJobId is provided', async () => {
21152119
const tables = [{ schema_name: 'public', table_name: 'users' }];
21162120

2117-
// First call - will execute and store in cache
2118-
await metadataOrchestrator.queryColumnsForTables(tables);
2121+
// First call with syncJobId - will execute and store in cache
2122+
await metadataOrchestrator.queryColumnsForTables(tables, 'default', { syncJobId: 'job-123' });
21192123

21202124
// Add a delay to ensure the first query has completed and cached its result
21212125
await new Promise(resolve => setTimeout(resolve, 100));
@@ -2127,8 +2131,8 @@ describe('QueryOrchestrator', () => {
21272131
// Our hash function should handle this correctly
21282132
const tables2 = [{ schema_name: 'public', table_name: 'users' }];
21292133

2130-
// Second call should use cache
2131-
const result = await metadataOrchestrator.queryColumnsForTables(tables2);
2134+
// Second call with same syncJobId should use cache
2135+
const result = await metadataOrchestrator.queryColumnsForTables(tables2, 'default', { syncJobId: 'job-123' });
21322136

21332137
expect(result).toEqual([
21342138
{
@@ -2165,11 +2169,11 @@ describe('QueryOrchestrator', () => {
21652169
expect(metadataMockDriver.getColumnsForSpecificTables).toHaveBeenCalledWith([]);
21662170
});
21672171

2168-
test('should force refresh when requested', async () => {
2172+
test('should refresh when syncJobId is not provided', async () => {
21692173
const tables = [{ schema_name: 'public', table_name: 'users' }];
21702174

21712175
await metadataOrchestrator.queryColumnsForTables(tables);
2172-
await metadataOrchestrator.queryColumnsForTables(tables, 'default', { forceRefresh: true });
2176+
await metadataOrchestrator.queryColumnsForTables(tables);
21732177

21742178
expect(metadataMockDriver.getColumnsForSpecificTables).toHaveBeenCalledTimes(2);
21752179
});
@@ -2217,11 +2221,11 @@ describe('QueryOrchestrator', () => {
22172221
// Mock driver error
22182222
metadataMockDriver.getSchemas.mockRejectedValueOnce(new Error('Database connection failed'));
22192223

2220-
await expect(metadataOrchestrator.queryDataSourceSchemas('default', { forceRefresh: true })).rejects.toThrow('Database connection failed');
2224+
await expect(metadataOrchestrator.queryDataSourceSchemas()).rejects.toThrow('Database connection failed');
22212225

22222226
// Should retry on next call
22232227
metadataMockDriver.getSchemas.mockResolvedValueOnce([{ schema_name: 'recovered' }]);
2224-
const result = await metadataOrchestrator.queryDataSourceSchemas('default', { forceRefresh: true });
2228+
const result = await metadataOrchestrator.queryDataSourceSchemas();
22252229
expect(result).toEqual([{ schema_name: 'recovered' }]);
22262230
});
22272231
});

0 commit comments

Comments
 (0)