Skip to content
50 changes: 43 additions & 7 deletions packages/matrix/helpers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,13 +165,49 @@ export async function createRealm(
endpoint: string,
name = endpoint,
) {
await page.locator('[data-test-add-workspace]').click();
await page.locator('[data-test-display-name-field]').fill(name);
await page.locator('[data-test-endpoint-field]').fill(endpoint);
await page.locator('[data-test-create-workspace-submit]').click();
await expect(page.locator(`[data-test-workspace="${name}"]`)).toHaveCount(1, {
timeout: 30_000,
});
// Creating a workspace provisions a matrix room + personal realm. Under
// load that can transiently fail: the modal surfaces an error
// (`data-test-error-message`) and stays open instead of closing and
// rendering the workspace tile. Submitting and waiting only for the tile
// then burns the full timeout on a modal that will never resolve. Instead
// wait for whichever outcome happens first and, on a surfaced error, retry
// the whole form from a clean modal (cancel re-opens with error cleared).
let workspaceTile = page.locator(`[data-test-workspace="${name}"]`);
let errorMessage = page.locator('[data-test-error-message]');
let maxAttempts = 3;
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
// A previous attempt's provisioning may have landed late — if the tile is
// already present, don't try to create a duplicate endpoint.
if ((await workspaceTile.count()) > 0) {
return;
}

await page.locator('[data-test-add-workspace]').click();
await page.locator('[data-test-display-name-field]').fill(name);
await page.locator('[data-test-endpoint-field]').fill(endpoint);
await page.locator('[data-test-create-workspace-submit]').click();

await expect(workspaceTile.or(errorMessage).first()).toBeVisible({
timeout: 30_000,
});
if ((await workspaceTile.count()) > 0) {
return;
}

let message = (await errorMessage.textContent())?.trim() ?? '(no message)';
if (attempt === maxAttempts) {
throw new Error(
`createRealm("${endpoint}") failed after ${maxAttempts} attempts: ${message}`,
);
}
console.log(
`[createRealm] "${endpoint}" attempt ${attempt}/${maxAttempts} errored, retrying: ${message}`,
);
// Dismiss the errored modal so the retry opens a fresh one (which clears
// the error and resets the fields).
await page.locator('[data-test-cancel-create-workspace]').click();
await expect(errorMessage).toBeHidden();
}
}

export async function openRoot(page: Page, url = testHost) {
Expand Down
10 changes: 10 additions & 0 deletions packages/matrix/helpers/isolated-realm-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,16 @@ export async function startPrerenderServer(
BOXEL_HOST_URL: 'https://localhost:4200',
LOG_LEVELS:
process.env.TEST_HARNESS_PRERENDER_LOG_LEVELS ?? process.env.LOG_LEVELS,
// One prerender server is shared by both Playwright workers
// (fullyParallel) for the whole shard. With the pool size unset it
// collapses to a fixed 4 tabs, which the shard's concurrent publish +
// index work can exhaust — the pool thrashes (`standby refill failed
// to produce a fresh tab`, cross-affinity steals) and realm-server
// requests stall, surfacing as 60s page.goto / _publish-realm
// timeouts. Enable the dynamic envelope: keep a 4-tab idle floor (no
// extra baseline memory) but let it burst to 8 under load.
PRERENDER_PAGE_POOL_MIN: process.env.PRERENDER_PAGE_POOL_MIN ?? '4',
PRERENDER_PAGE_POOL_MAX: process.env.PRERENDER_PAGE_POOL_MAX ?? '8',
};
let prerenderArgs = [
'--transpileOnly',
Expand Down
Loading