ci(core): Reduce memory usage in tests (part-2) (no-changelog) (#7671)

This also gets rid of `Db.collection`, which was another source of
circular dependencies.
This commit is contained in:
कारतोफ्फेलस्क्रिप्ट™
2023-11-10 15:04:26 +01:00
committed by GitHub
parent 37dd658dc5
commit 000e76e3b4
174 changed files with 892 additions and 808 deletions

View File

@@ -5,7 +5,8 @@ import type { ICredentialsDb } from '@/Interfaces';
import { RoleService } from '@/services/role.service';
import type { CredentialPayload } from '../types';
import Container from 'typedi';
import { CredentialsRepository, SharedCredentialsRepository } from '@/databases/repositories';
import { CredentialsRepository } from '@db/repositories/credentials.repository';
import { SharedCredentialsRepository } from '@db/repositories/sharedCredentials.repository';
async function encryptCredentialData(credential: CredentialsEntity) {
const { createCredentialsFromCredentialsEntity } = await import('@/CredentialsHelper');

View File

@@ -2,7 +2,8 @@ import Container from 'typedi';
import type { ExecutionData } from '@db/entities/ExecutionData';
import type { ExecutionEntity } from '@db/entities/ExecutionEntity';
import type { WorkflowEntity } from '@db/entities/WorkflowEntity';
import { ExecutionDataRepository, ExecutionRepository } from '@db/repositories';
import { ExecutionRepository } from '@db/repositories/execution.repository';
import { ExecutionDataRepository } from '@db/repositories/executionData.repository';
export async function createManyExecutions(
amount: number,

View File

@@ -1,7 +1,8 @@
import Container from 'typedi';
import type { TagEntity } from '@db/entities/TagEntity';
import type { WorkflowEntity } from '@db/entities/WorkflowEntity';
import { TagRepository, WorkflowTagMappingRepository } from '@db/repositories';
import { TagRepository } from '@db/repositories/tag.repository';
import { WorkflowTagMappingRepository } from '@db/repositories/workflowTagMapping.repository';
import { generateNanoId } from '@db/utils/generators';
import { randomName } from '../random';

View File

@@ -3,7 +3,8 @@ import { hash } from 'bcryptjs';
import { AuthIdentity } from '@db/entities/AuthIdentity';
import type { Role } from '@db/entities/Role';
import type { User } from '@db/entities/User';
import { AuthIdentityRepository, UserRepository } from '@db/repositories';
import { AuthIdentityRepository } from '@db/repositories/authIdentity.repository';
import { UserRepository } from '@db/repositories/user.repository';
import { TOTPService } from '@/Mfa/totp.service';
import { MfaService } from '@/Mfa/mfa.service';

View File

@@ -1,7 +1,7 @@
import Container from 'typedi';
import { v4 as uuid } from 'uuid';
import type { WorkflowHistory } from '@db/entities/WorkflowHistory';
import { WorkflowHistoryRepository } from '@db/repositories';
import { WorkflowHistoryRepository } from '@db/repositories/workflowHistory.repository';
export async function createWorkflowHistoryItem(
workflowId: string,

View File

@@ -2,7 +2,8 @@ import Container from 'typedi';
import { v4 as uuid } from 'uuid';
import type { User } from '@db/entities/User';
import type { WorkflowEntity } from '@db/entities/WorkflowEntity';
import { SharedWorkflowRepository, WorkflowRepository } from '@db/repositories';
import { SharedWorkflowRepository } from '@db/repositories/sharedWorkflow.repository';
import { WorkflowRepository } from '@db/repositories/workflow.repository';
import { getWorkflowEditorRole, getWorkflowOwnerRole } from './roles';
export async function createManyWorkflows(

View File

@@ -8,12 +8,10 @@ import { entities } from '@db/entities';
import { mysqlMigrations } from '@db/migrations/mysqldb';
import { postgresMigrations } from '@db/migrations/postgresdb';
import { sqliteMigrations } from '@db/migrations/sqlite';
import { TagRepository, WorkflowTagMappingRepository } from '@/databases/repositories';
import { DB_INITIALIZATION_TIMEOUT } from './constants';
import { randomString } from './random';
import type { CollectionName, PostgresSchemaSection } from './types';
import { separate } from '@/utils';
import type { PostgresSchemaSection } from './types';
export type TestDBType = 'postgres' | 'mysql';
@@ -88,23 +86,40 @@ export async function terminate() {
await Db.close();
}
// Can't use `Object.keys(entities)` here because some entities have a `Entity` suffix, while the repositories don't
const repositories = [
'AuthIdentity',
'AuthProviderSyncHistory',
'Credentials',
'EventDestinations',
'ExecutionData',
'ExecutionMetadata',
'Execution',
'InstalledNodes',
'InstalledPackages',
'Role',
'Settings',
'SharedCredentials',
'SharedWorkflow',
'Tag',
'User',
'Variables',
'Webhook',
'Workflow',
'WorkflowHistory',
'WorkflowStatistics',
'WorkflowTagMapping',
] as const;
/**
* Truncate specific DB tables in a test DB.
*/
export async function truncate(collections: CollectionName[]) {
const [tag, rest] = separate(collections, (c) => c === 'Tag');
if (tag.length) {
await Container.get(TagRepository).delete({});
await Container.get(WorkflowTagMappingRepository).delete({});
}
for (const collection of rest) {
if (typeof collection === 'string') {
await Db.collections[collection].delete({});
} else {
await Container.get(collection as { new (): Repository<any> }).delete({});
}
export async function truncate(names: Array<(typeof repositories)[number]>) {
for (const name of names) {
const RepositoryClass: { new (): Repository<any> } = (
await import(`@db/repositories/${name.charAt(0).toLowerCase() + name.slice(1)}.repository`)
)[`${name}Repository`];
await Container.get(RepositoryClass).delete({});
}
}

View File

@@ -5,12 +5,7 @@ import type { Server } from 'http';
import type { CredentialsEntity } from '@db/entities/CredentialsEntity';
import type { User } from '@db/entities/User';
import type { BooleanLicenseFeature, ICredentialsDb, IDatabaseCollections } from '@/Interfaces';
import type { DataSource, Repository } from 'typeorm';
export type CollectionName =
| keyof IDatabaseCollections
| { new (dataSource: DataSource): Repository<any> };
import type { BooleanLicenseFeature, ICredentialsDb } from '@/Interfaces';
type EndpointGroup =
| 'me'

View File

@@ -3,7 +3,8 @@ import { InstalledPackages } from '@db/entities/InstalledPackages';
import { randomName } from '../random';
import { COMMUNITY_NODE_VERSION, COMMUNITY_PACKAGE_VERSION } from '../constants';
import { InstalledNodesRepository, InstalledPackagesRepository } from '@/databases/repositories';
import { InstalledNodesRepository } from '@db/repositories/installedNodes.repository';
import { InstalledPackagesRepository } from '@db/repositories/installedPackages.repository';
import Container from 'typedi';
export const mockPackageName = () => NODE_PACKAGE_PREFIX + randomName();

View File

@@ -10,15 +10,14 @@ import type request from 'supertest';
import { v4 as uuid } from 'uuid';
import config from '@/config';
import * as Db from '@/Db';
import { WorkflowEntity } from '@db/entities/WorkflowEntity';
import { AUTH_COOKIE_NAME } from '@/constants';
import { LoadNodesAndCredentials } from '@/LoadNodesAndCredentials';
import { mockInstance } from './mocking';
import { SettingsRepository } from '@db/repositories/settings.repository';
import { mockNodeTypesData } from '../../../unit/Helpers';
import { mockInstance } from '../../../shared/mocking';
export { mockInstance } from './mocking';
export { setupTestServer } from './testServer';
// ----------------------------------
@@ -108,7 +107,7 @@ export function getAuthToken(response: request.Response, authCookieName = AUTH_C
// ----------------------------------
export async function isInstanceOwnerSetUp() {
const { value } = await Db.collections.Settings.findOneByOrFail({
const { value } = await Container.get(SettingsRepository).findOneByOrFail({
key: 'userManagement.isInstanceOwnerSetUp',
});
@@ -118,7 +117,7 @@ export async function isInstanceOwnerSetUp() {
export const setInstanceOwnerSetUp = async (value: boolean) => {
config.set('userManagement.isInstanceOwnerSetUp', value);
await Db.collections.Settings.update(
await Container.get(SettingsRepository).update(
{ key: 'userManagement.isInstanceOwnerSetUp' },
{ value: JSON.stringify(value) },
);

View File

@@ -1,12 +0,0 @@
import { Container } from 'typedi';
import { mock } from 'jest-mock-extended';
import type { DeepPartial } from 'ts-essentials';
export const mockInstance = <T>(
ctor: new (...args: unknown[]) => T,
data: DeepPartial<T> | undefined = undefined,
) => {
const instance = mock<T>(data);
Container.set(ctor, instance);
return instance;
};

View File

@@ -14,18 +14,12 @@ import { rawBodyReader, bodyParser, setupAuthMiddlewares } from '@/middlewares';
import { InternalHooks } from '@/InternalHooks';
import { PostHogClient } from '@/posthog';
import { License } from '@/License';
import {
SettingsRepository,
SharedCredentialsRepository,
SharedWorkflowRepository,
} from '@/databases/repositories';
import { Logger } from '@/Logger';
import { mockInstance } from '../../../shared/mocking';
import * as testDb from '../../shared/testDb';
import { AUTHLESS_ENDPOINTS, PUBLIC_API_REST_PATH_SEGMENT, REST_PATH_SEGMENT } from '../constants';
import type { SetupProps, TestServer } from '../types';
import { mockInstance } from './mocking';
/**
* Plugin to prefix a path segment into a request URL pathname.
@@ -217,6 +211,7 @@ export const setupTestServer = ({
case 'owner':
const { UserService } = await import('@/services/user.service');
const { SettingsRepository } = await import('@db/repositories/settings.repository');
const { OwnerController } = await import('@/controllers/owner.controller');
registerController(
app,
@@ -232,6 +227,12 @@ export const setupTestServer = ({
break;
case 'users':
const { SharedCredentialsRepository } = await import(
'@db/repositories/sharedCredentials.repository'
);
const { SharedWorkflowRepository } = await import(
'@db/repositories/sharedWorkflow.repository'
);
const { ActiveWorkflowRunner } = await import('@/ActiveWorkflowRunner');
const { ExternalHooks } = await import('@/ExternalHooks');
const { JwtService } = await import('@/services/jwt.service');