Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 55 additions & 49 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -419,61 +419,67 @@ jobs:
-d '{"context":"Matrix Playwright tests report","description":"'"$description"'","target_url":"'"$PLAYWRIGHT_REPORT_URL"'","state":"'"$state"'"}'

realm-server-test:
name: Realm Server Tests
name: Realm Server Tests (shard ${{ matrix.shard }})
needs: [change-check, test-web-assets]
if: needs.change-check.outputs.realm-server == 'true' || github.ref == 'refs/heads/main' || needs.change-check.outputs.run_all == 'true'
runs-on: ubuntu-latest
concurrency:
group: realm-server-test-${{ matrix.testModule }}-${{ github.head_ref || github.run_id }}
group: realm-server-test-${{ matrix.shard }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
strategy:
fail-fast: false
matrix:
testModule:
[
"auth-client-test.ts",
"billing-test.ts",
"card-dependencies-endpoint-test.ts",
"card-endpoints-test.ts",
"card-source-endpoints-test.ts",
"definition-lookup-test.ts",
"file-watcher-events-test.ts",
"indexing-test.ts",
"transpile-test.ts",
"module-syntax-test.ts",
"permissions/permission-checker-test.ts",
"prerendering-test.ts",
"prerender-server-test.ts",
"prerender-manager-test.ts",
"prerender-proxy-test.ts",
"remote-prerenderer-test.ts",
"queue-test.ts",
"realm-endpoints/dependencies-test.ts",
"realm-endpoints/directory-test.ts",
"realm-endpoints/info-test.ts",
"realm-endpoints/lint-test.ts",
"realm-endpoints/mtimes-test.ts",
"realm-endpoints/permissions-test.ts",
"realm-endpoints/publishability-test.ts",
"realm-endpoints/search-test.ts",
"realm-endpoints/user-test.ts",
"realm-endpoints-test.ts",
"search-prerendered-test.ts",
"types-endpoint-test.ts",
"server-endpoints-test.ts",
"server-endpoints/search-test.ts",
"server-endpoints/search-prerendered-test.ts",
"virtual-network-test.ts",
"atomic-endpoints-test.ts",
"request-forward-test.ts",
"publish-unpublish-realm-test.ts",
"boxel-domain-availability-test.ts",
"claim-boxel-domain-test.ts",
"delete-boxel-claimed-domain-test.ts",
"get-boxel-claimed-domain-test.ts",
"realm-auth-test.ts",
"queries-test.ts",
]
include:
- shard: 1
testModules:
- server-endpoints-test.ts
- atomic-endpoints-test.ts
- request-forward-test.ts
- realm-endpoints/info-test.ts
- realm-endpoints/user-test.ts
- file-watcher-events-test.ts
- types-endpoint-test.ts
- prerender-manager-test.ts
- prerender-proxy-test.ts
- transpile-test.ts
- server-endpoints/search-prerendered-test.ts
- shard: 2
testModules:
- card-endpoints-test.ts
- publish-unpublish-realm-test.ts
- realm-endpoints/lint-test.ts
- claim-boxel-domain-test.ts
- realm-endpoints/publishability-test.ts
- boxel-domain-availability-test.ts
- realm-endpoints/dependencies-test.ts
- queue-test.ts
- remote-prerenderer-test.ts
- permissions/permission-checker-test.ts
- shard: 3
testModules:
- realm-endpoints-test.ts
- prerendering-test.ts
- search-prerendered-test.ts
- card-dependencies-endpoint-test.ts
- delete-boxel-claimed-domain-test.ts
- get-boxel-claimed-domain-test.ts
- realm-endpoints/mtimes-test.ts
- billing-test.ts
- virtual-network-test.ts
- module-syntax-test.ts
- shard: 4
testModules:
- indexing-test.ts
- card-source-endpoints-test.ts
- realm-endpoints/search-test.ts
- server-endpoints/search-test.ts
- realm-endpoints/permissions-test.ts
- realm-endpoints/directory-test.ts
- definition-lookup-test.ts
- prerender-server-test.ts
- realm-auth-test.ts
- auth-client-test.ts
- queries-test.ts
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # 4.2.2
- uses: ./.github/actions/init
Expand Down Expand Up @@ -507,15 +513,15 @@ jobs:
run: pnpm test:wait-for-servers
working-directory: packages/realm-server
env:
TEST_MODULE: ${{matrix.testModule}}
TEST_MODULES: ${{ join(matrix.testModules, '|') }}
- name: Print realm server logs
if: always()
run: cat /tmp/server.log
- name: Prepare artifact name
id: artifact_name
if: always()
run: |
export SAFE_ARTIFACT_NAME=$(echo ${{ matrix.testModule }} | sed 's/[/]/_/g')
export SAFE_ARTIFACT_NAME=shard-${{ matrix.shard }}
echo "artifact_name=$SAFE_ARTIFACT_NAME" >> "$GITHUB_OUTPUT"
- name: Upload realm server log
uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # 4.6.1
Expand Down
13 changes: 8 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ You can also use `start:development` if you want the functionality of `start:all

Optional environment variables for `start:development`:

- `USE_EXTERNAL_CATALOG=1` to load `/catalog` from `packages/catalog/contents` (cloned from the `boxel-catalog` repo).
- `USE_EXTERNAL_CATALOG=1` to load `/catalog` from `packages/catalog/contents` (cloned from the `boxel-catalog` repo).

### Card Pre-rendering

Expand Down Expand Up @@ -394,12 +394,15 @@ The tests are available at `http://localhost:4200/tests`

### Realm Server Node tests

First make sure to generate the host app's `dist/` output in order to support card pre-rendering by first starting the host app (instructions above). If you want to make the host app's `dist/` output without starting the host app, you can run `pnpm build` in the host app's workspace.

To run the `packages/realm-server/` workspace tests start:

1. `pnpm start:all` in the `packages/realm-server/` to serve _both_ the base realm and the realm that serves the test cards for node.
2. Run `pnpm test` in the `packages/realm-server/` workspace to run the realm node tests. `TEST_MODULE=realm-endpoints-test.ts pnpm test-module` is an example of how to run a single test module.
1. The host application on port 4200. You can do this by running `pnpm start` in the `packages/host/` workspace, or if you have a built folder you can serve it with a static server with `pnpm serve:dist`.
2. The base realm and associated workers, postgres and synapse. You can do this by running `pnpm start:all` in the `packages/realm-server/` workspace, or `pnpm:start-services-for-host-tests` for a more lightweight setup.
3. Run the realm server tests:

- `pnpm test` in the `packages/realm-server/` workspace to run the realm node tests in full (~1hr).
- `TEST_MODULES="types-endpoint-test.ts|another-test-module.ts" pnpm test` in the `packages/realm-server/` workspace to run tests for a subset of modules.
- `TEST_MODULE="types-endpoint-test.ts" pnpm test-module` in the `packages/realm-server/` workspace to run tests for a specific module.

### Boxel UI

Expand Down
2 changes: 1 addition & 1 deletion packages/realm-server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@
"start:smtp": "cd ../matrix && pnpm assert-smtp-running",
"start:pg": "./scripts/start-pg.sh",
"stop:pg": "./scripts/stop-pg.sh",
"test:wait-for-servers": "WAIT_ON_TIMEOUT=900000 NODE_NO_WARNINGS=1 start-server-and-test 'pnpm run wait' 'http-get://localhost:4201/base/_readiness-check?acceptHeader=application%2Fvnd.api%2Bjson' 'pnpm run wait' 'http-get://localhost:4202/node-test/_readiness-check?acceptHeader=application%2Fvnd.api%2Bjson|http://localhost:8008|http://localhost:5001' 'test-module'",
"test:wait-for-servers": "WAIT_ON_TIMEOUT=900000 NODE_NO_WARNINGS=1 start-server-and-test 'pnpm run wait' 'http-get://localhost:4201/base/_readiness-check?acceptHeader=application%2Fvnd.api%2Bjson' 'pnpm run wait' 'http-get://localhost:4202/node-test/_readiness-check?acceptHeader=application%2Fvnd.api%2Bjson|http://localhost:8008|http://localhost:5001' 'test'",
"setup:base-in-deployment": "mkdir -p /persistent/base && rsync --dry-run --itemize-changes --checksum --recursive --delete ../base/. /persistent/base/ && rsync --checksum --recursive --delete ../base/. /persistent/base/",
"setup:experiments-in-deployment": "mkdir -p /persistent/experiments && rsync --dry-run --itemize-changes --checksum --recursive ../experiments-realm/. /persistent/experiments/ && rsync --checksum --recursive ../experiments-realm/. /persistent/experiments/",
"setup:catalog-in-deployment": "mkdir -p /persistent/catalog && rsync --dry-run --itemize-changes --checksum --recursive --delete ../catalog-realm/. /persistent/catalog/ && rsync --checksum --recursive --delete ../catalog-realm/. /persistent/catalog/",
Expand Down
32 changes: 29 additions & 3 deletions packages/realm-server/prerender/page-pool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,18 @@ export class PagePool {
#standbyTimeoutMs: number;
#ensuringStandbys: Promise<void> | null = null;
#creatingStandbys = 0;
#shuttingDown = false;
#logError(message: string, error?: unknown) {
if (this.#shuttingDown) {
log.debug(`${message} (suppressed during shutdown)`, error);
return;
}
if (typeof error === 'undefined') {
log.error(message);
} else {
log.error(message, error);
}
}

constructor(options: {
maxPages: number;
Expand All @@ -53,6 +65,11 @@ export class PagePool {
this.#standbyTimeoutMs = options.standbyTimeoutMs ?? 30_000;
}

markShuttingDown(): void {
this.#shuttingDown = true;
this.#ensuringStandbys = null;
}

getWarmRealms(): string[] {
return [...this.#realmPages.keys()];
}
Expand Down Expand Up @@ -166,6 +183,9 @@ export class PagePool {
}

async #ensureStandbyPool(): Promise<void> {
if (this.#shuttingDown) {
return;
}
if (this.#ensuringStandbys) {
return await this.#ensuringStandbys;
}
Expand All @@ -176,6 +196,9 @@ export class PagePool {
}

async #ensureStandbyPoolInternal(): Promise<void> {
if (this.#shuttingDown) {
return;
}
for (;;) {
let desired = this.#desiredStandbyCount();
let current = this.#currentStandbyCount();
Expand Down Expand Up @@ -229,14 +252,17 @@ export class PagePool {
}

async #createStandbyWithRetries(): Promise<StandbyEntry | undefined> {
if (this.#shuttingDown) {
return undefined;
}
let attempt = 0;
let backoffMs = STANDBY_BACKOFF_MS;
while (attempt < STANDBY_CREATION_RETRIES) {
attempt++;
try {
return await this.#createStandby();
} catch (e) {
log.error(
this.#logError(
`Standby creation attempt ${attempt} failed (page pool capacity ${this.#totalContextCount()}/${this.#maxPages + 1}):`,
e,
);
Expand Down Expand Up @@ -270,7 +296,7 @@ export class PagePool {
this.#standbys.add(entry);
return entry;
} catch (e) {
log.error('Error creating standby page:', e);
this.#logError('Error creating standby page:', e);
if (context) {
try {
await context.close();
Expand Down Expand Up @@ -311,7 +337,7 @@ export class PagePool {
]);
if (result && typeof result === 'object' && 'timeout' in result) {
let message = `Standby page ${pageId} timed out after ${this.#standbyTimeoutMs}ms`;
log.error(message);
this.#logError(message);
throw new Error(message);
}
return result;
Expand Down
Loading