Speed up app deployment 1000+ test (#7691)

Co-authored-by: Adam Benhassen <adambenhassen@hotmail.com>
This commit is contained in:
jdolle 2026-02-17 03:18:49 -08:00 committed by GitHub
parent 24d46fbc14
commit eb6984efa0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 67 additions and 31 deletions

View file

@ -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}`);
}
}

View file

@ -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;
}
});