mirror of
https://github.com/graphql-hive/console
synced 2026-04-21 14:37:17 +00:00
Speed up app deployment 1000+ test (#7691)
Co-authored-by: Adam Benhassen <adambenhassen@hotmail.com>
This commit is contained in:
parent
24d46fbc14
commit
eb6984efa0
2 changed files with 67 additions and 31 deletions
|
|
@ -30,3 +30,23 @@ export async function clickHouseQuery<T>(query: string): Promise<{
|
|||
|
||||
return response.json();
|
||||
}
|
||||
|
||||
export async function clickHouseInsert<T>(query: string): Promise<void> {
|
||||
const clickhouseAddress = await getServiceHost('clickhouse', 8123);
|
||||
const endpoint = `http://${clickhouseAddress}/?default_format=JSON`;
|
||||
const response = await fetch(endpoint, {
|
||||
method: 'POST',
|
||||
body: query,
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
'Accept-Encoding': 'gzip',
|
||||
Authorization: `Basic ${credentials}`,
|
||||
},
|
||||
});
|
||||
|
||||
if (response.status !== 200) {
|
||||
const body = await response.text();
|
||||
|
||||
throw new Error(`Failed CH query ${query} with status ${response.status} and body:\n${body}`);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
import { buildASTSchema, parse } from 'graphql';
|
||||
import { createLogger } from 'graphql-yoga';
|
||||
import { sql } from 'slonik';
|
||||
import { pollFor } from 'testkit/flow';
|
||||
import { initSeed } from 'testkit/seed';
|
||||
import { getServiceHost } from 'testkit/utils';
|
||||
import { createHive } from '@graphql-hive/core';
|
||||
import { clickHouseInsert, clickHouseQuery } from '../../testkit/clickhouse';
|
||||
import { graphql } from '../../testkit/gql';
|
||||
import { execute } from '../../testkit/graphql';
|
||||
|
||||
|
|
@ -2031,50 +2033,62 @@ test('activeAppDeployments filters by neverUsedAndCreatedBefore', async () => {
|
|||
});
|
||||
|
||||
test('activeAppDeployments works for > 1000 records with a date filter (neverUsedAndCreatedBefore) set', async () => {
|
||||
const { createOrg, ownerToken } = await initSeed().createOwner();
|
||||
const seed = await initSeed();
|
||||
await using conn = await seed.createDbConnection();
|
||||
const { createOrg, ownerToken } = await seed.createOwner();
|
||||
const { createProject, setFeatureFlag, organization } = await createOrg();
|
||||
await setFeatureFlag('appDeployments', true);
|
||||
const { createTargetAccessToken, project, target } = await createProject();
|
||||
const token = await createTargetAccessToken({});
|
||||
const { project, target } = await createProject();
|
||||
|
||||
// seed 1,200 app deployments
|
||||
const apps = ['web-app', 'mobile-app', 'admin-dashboard', 'cli-tool'];
|
||||
const appDeployments = apps.flatMap((app, minor) =>
|
||||
Array.from({ length: 300 }).map((_, patch) => ({
|
||||
appName: app,
|
||||
appVersion: [1, minor, patch].join('.'),
|
||||
})),
|
||||
const now = new Date().toISOString();
|
||||
const appDeploymentRows = apps.flatMap((app, minor) =>
|
||||
Array.from({ length: 300 }).map(
|
||||
(_, patch) =>
|
||||
[
|
||||
target.id, // target_id
|
||||
app, // name
|
||||
[1, minor, patch].join('.'), // version
|
||||
now, // activated_at
|
||||
] as const,
|
||||
),
|
||||
);
|
||||
|
||||
for (const { appName, appVersion } of appDeployments) {
|
||||
// Create and activate an app deployment
|
||||
await execute({
|
||||
document: CreateAppDeployment,
|
||||
variables: {
|
||||
input: {
|
||||
appName,
|
||||
appVersion,
|
||||
},
|
||||
},
|
||||
authToken: token.secret,
|
||||
}).then(res => res.expectNoGraphQLErrors());
|
||||
// insert into postgres
|
||||
const result = await conn.pool.query(sql`
|
||||
INSERT INTO app_deployments ("target_id", "name", "version", "activated_at")
|
||||
SELECT * FROM ${sql.unnest(appDeploymentRows, ['uuid', 'text', 'text', 'timestamptz'])}
|
||||
RETURNING "id", "target_id", "name", "version"
|
||||
`);
|
||||
expect(result.rowCount).toBe(1200);
|
||||
|
||||
await execute({
|
||||
document: ActivateAppDeployment,
|
||||
variables: {
|
||||
input: {
|
||||
appName,
|
||||
appVersion,
|
||||
},
|
||||
},
|
||||
authToken: token.secret,
|
||||
}).then(res => res.expectNoGraphQLErrors());
|
||||
}
|
||||
// insert into clickhouse and activate
|
||||
const query = `INSERT INTO app_deployments (
|
||||
"target_id"
|
||||
,"app_deployment_id"
|
||||
,"app_name"
|
||||
,"app_version"
|
||||
,"is_active"
|
||||
) VALUES
|
||||
${result.rows
|
||||
.map(
|
||||
r => `(
|
||||
'${r['target_id']}'
|
||||
, '${r['id']}'
|
||||
, '${r['name']}'
|
||||
, '${r['version']}'
|
||||
, True
|
||||
)`,
|
||||
)
|
||||
.join(',')};`;
|
||||
await clickHouseInsert(query);
|
||||
|
||||
// Query for deployments never used and created before tomorrow
|
||||
const tomorrow = new Date();
|
||||
tomorrow.setDate(tomorrow.getDate() + 1);
|
||||
|
||||
let cursor: string | undefined;
|
||||
for (let page = 0; page < Math.ceil(1200 / 20); page++) {
|
||||
const result = await execute({
|
||||
document: GetActiveAppDeployments,
|
||||
|
|
@ -2085,6 +2099,7 @@ test('activeAppDeployments works for > 1000 records with a date filter (neverUse
|
|||
targetSlug: target.slug,
|
||||
},
|
||||
first: 20,
|
||||
after: cursor,
|
||||
filter: {
|
||||
neverUsedAndCreatedBefore: tomorrow.toISOString(),
|
||||
},
|
||||
|
|
@ -2093,6 +2108,7 @@ test('activeAppDeployments works for > 1000 records with a date filter (neverUse
|
|||
}).then(res => res.expectNoGraphQLErrors());
|
||||
// all should be full pages
|
||||
expect(result.target?.activeAppDeployments.edges).toHaveLength(20);
|
||||
cursor = result.target?.activeAppDeployments.pageInfo.endCursor;
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue