add drodil's getEntities performance test

Signed-off-by: Fredrik Adelöw <freben@gmail.com>
This commit is contained in:
Fredrik Adelöw
2024-09-14 11:07:52 +02:00
parent ffe31a8ae0
commit 9a804f4401
2 changed files with 156 additions and 3 deletions
@@ -0,0 +1,146 @@
/*
* Copyright 2024 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { describePerformanceTest, performanceTraceEnabled } from './lib/env';
import { startTestBackend, TestDatabases } from '@backstage/backend-test-utils';
import { applyDatabaseMigrations } from '../../database/migrations';
import {
SyntheticLoadEntitiesProcessor,
SyntheticLoadEntitiesProvider,
SyntheticLoadOptions,
} from './lib/catalogModuleSyntheticLoadEntities';
import { CatalogClient } from '@backstage/catalog-client';
import {
coreServices,
createBackendModule,
createServiceFactory,
} from '@backstage/backend-plugin-api';
import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha';
import { Knex } from 'knex';
jest.setTimeout(600_000);
const traceLog: typeof console.log = performanceTraceEnabled
? console.log
: () => {};
const completionPolling = async (load: SyntheticLoadOptions, knex: Knex) => {
const { baseEntitiesCount, childrenCount } = load;
const expectedTotal = baseEntitiesCount + baseEntitiesCount * childrenCount;
return new Promise<void>((resolve, reject) => {
const interval = setInterval(async () => {
try {
const stitchedCount = await knex('final_entities')
.count({ count: '*' })
.whereNotNull('final_entity')
.then(rows => Number(rows[0].count));
if (stitchedCount === expectedTotal) {
clearInterval(interval);
resolve();
}
} catch (error) {
clearInterval(interval);
reject(error);
}
}, 1000);
});
};
describePerformanceTest('getEntitiesPerformanceTest', () => {
const databases = TestDatabases.create({
ids: [/* 'MYSQL_8', */ 'POSTGRES_16', /* 'POSTGRES_12',*/ 'SQLITE_3'],
disableDocker: false,
});
it.each(databases.eachSupportedId())(
'fetch entities, %p',
async databaseId => {
const knex = await databases.init(databaseId);
await applyDatabaseMigrations(knex);
const load: SyntheticLoadOptions = {
baseEntitiesCount: 2000,
baseRelationsCount: 3,
baseRelationsSkew: 0.3,
childrenCount: 3,
};
traceLog('Starting test backend');
const backend = await startTestBackend({
features: [
import('@backstage/plugin-catalog-backend/alpha'),
createServiceFactory({
service: coreServices.database,
deps: {},
factory: () => ({ getClient: async () => knex }),
}),
createBackendModule({
pluginId: 'catalog',
moduleId: 'synthetic-load-entities',
register(reg) {
reg.registerInit({
deps: {
catalog: catalogProcessingExtensionPoint,
},
async init({ catalog }) {
catalog.addEntityProvider(
new SyntheticLoadEntitiesProvider(load, {}),
);
catalog.addProcessor(
new SyntheticLoadEntitiesProcessor(load),
);
},
});
},
}),
],
});
const expectedTotal =
load.baseEntitiesCount + load.baseEntitiesCount * load.childrenCount;
traceLog(`Waiting for completion polling of ${expectedTotal} entities`);
await expect(completionPolling(load, knex)).resolves.toBeUndefined();
const client = new CatalogClient({
discoveryApi: {
getBaseUrl: jest
.fn()
.mockResolvedValue(
`http://localhost:${backend.server.port()}/api/catalog`,
),
},
});
const start = Date.now();
traceLog(`[${databaseId}] Starting to fetch ${expectedTotal} entities`);
// Fetch all entities
const response = await client.getEntities();
expect(response.items).toHaveLength(expectedTotal);
const fetchDuration = Date.now() - start;
traceLog(
`[${databaseId}] Fetched ${expectedTotal} entities in ${fetchDuration}ms`,
);
await backend.stop();
await knex.destroy();
},
);
});
@@ -14,9 +14,16 @@
* limitations under the License.
*/
export const performanceTraceEnabled = !!process.env.PERFORMANCE_TRACE;
import yn from 'yn';
export const describePerformanceTest: jest.Describe = process.env
.PERFORMANCE_TEST
export const performanceTraceEnabled = yn(process.env.PERFORMANCE_TRACE, {
default: false,
});
export const performanceTestEnabled = yn(process.env.PERFORMANCE_TEST, {
default: false,
});
export const describePerformanceTest: jest.Describe = performanceTestEnabled
? describe
: describe.skip;