Files
jobtrackingapp/docs/redesign/phase-9/p9-requal-01/PERFORMANCE.md
T
cesnimda 3727a723e8
MariaDB persistence qualification / mariadb (push) Failing after 7s
docs: publish Phase 9 requalification decisions and evidence
2026-10-24 18:32:24 +02:00

9.3 KiB
Raw Blame History

P9-REQUAL-01 performance protocol

Status: PASS on real MariaDB12.2.2 after the documented fixture/provider repairs. Historical P9-05 and RD21 sustained fixtures remain unchanged. Their short SQLite observations are not evidence for this lane. Actual runner results must be added below after the exclusive run.

The only new executable source is in performance/. It extends job-tracker-ui/playwright.mariadb.config.ts, preserving the canonical disposable-schema guard, MariaDB provider/version and reuseExistingServer: false on both servers. The additional guard requires port 33308 and a prebuilt production static frontend. No production code, dependencies, SQLite database, mock database or mocked API response is introduced.

Runner prerequisites

  • Run alone after other test/build/browser/load lanes stop. Free ports 5302 and 3300; existing listeners cause failure, never reuse.
  • The trusted root runner creates and later cleans up one generated jt_it_<32 lowercase hex> schema on its pinned mariadb:12.2.2 disposable Docker instance at 127.0.0.1:33308.
  • Supply JOBTRACKER_MARIADB_BROWSER_PORT=33308, JOBTRACKER_MARIADB_CLIENT=<absolute native mariadb/mysql executable>, and JOBTRACKER_MARIADB_BROWSER_CONNECTION=Server=127.0.0.1;Port=33308;Database=<generated schema>;User ID=root;Password=jt-integration-only;SslMode=None.
  • Supply PLAYWRIGHT_STATIC_EXPORT=true and PLAYWRIGHT_PREBUILT_EXPORT=true. Build Release backend and frontend from the frozen source before this lane. Preserve source/build/report hashes and timestamps in the root evidence ledger. This fixture does not establish source freshness itself.
  • Execute from job-tracker-ui so the inherited server commands and .artifacts paths resolve correctly. Do not enable server reuse or rerun failed tests silently. The config sets retries to zero even in CI.

Run after setting the above environment in the runner (all shell invocations use RTK):

rtk node node_modules/@playwright/test/cli.js test --config=../docs/redesign/phase-9/p9-requal-01/performance/playwright.config.ts

Fresh output is at repository-root .artifacts/p9-requal-01/performance/: playwright-results.json plus test-results/, including a JSON attachment named p9-requal-01-mariadb-performance. Preserve failure attachments as well as successful ones.

Measured workload and invariants

Setup uses the current API contract: create one free synthetic owner, one owned company, exactly 250 applications (record every returned ID), eight Career Profile roles with six long multilingual bullets each using the current expected revision, and one minimal CV variant. Free membership avoids the existing Premium creation-time model summarizer; this is a database/UI workload. Setup ends before the measured clock starts. SQL independently verifies MariaDB 12.2.2 and reads committed state in read-only transactions through the supplied native client.

Before starting that clock, fail-fast preflight checks each of the four endpoint response shapes/content once and performs one readiness-checked navigation to each workspace. Preflight navigation/telemetry is separately labelled and excluded from workload counts and percentiles. The attachment records setup/preflight/workload/preservation/complete phase and preflightPassed; a preflight failure does not pretend a 15-minute run occurred. Source checks confirm CareerProfileService derives startDate/endDate from supplied start/end, and CvRenderModel consumes normalized dates with source-date fallback. JobTable owns data-job-row-id; Dashboard renders the English Tracked jobs: 250 accessible link without a paid-role condition when its default summary widget has jobs.

The measured interval is an actual monotonic-clock 900000 ms minimum, enforced in source with no duration override. The test timeout is 18 minutes, including setup and final checks. Exactly two independent API reader contexts run until the deadline. Each sequential reader rotates stats, board, Career Profile and documents, waits at least 500 ms after completion before its next request, has a 10-second per-request timeout, and never catches up with bursts. Native browser requests are additional UI traffic and are not counted as synthetic reader operations. Response bodies are disposed after measurement to avoid accumulating load-generator storage.

Twenty browser navigations are scheduled every 45 seconds across the interval (five rounds of Dashboard, Table, Board and long CV). Dashboard must show 250 jobs, Table must render a row, and Board must contain the exact seeded ID set. CV assertions retain the historical page-readiness and final-marker-on-last-page checks. Errors are recorded once and the timed interval continues; all failures fail the final gate. Playwright locator polling is ordinary readiness checking, not a workload retry.

Before and after the interval, independent SQL snapshots must match exactly: 250 unique application IDs, owned/deleted counts, every tenant's application count, canonical profile JSON and revision, Identity projection JSON and Career Profile history count. API board membership and full saved-profile equality are checked again afterward; board and profile reader responses also assert exact content throughout. The fixture leaves synthetic data for the trusted disposable-schema cleanup; it never deletes or changes other tenants.

The attachment retains every reader attempt (worker/endpoint/start offset/duration/status/bytes/error), all navigation outcomes, p50/p95/p99/max successful response latency with explicit attempt/failure counts overall and per endpoint, and failures separately for navigation. Percentiles use the nearest-rank rule. Descriptive telemetry includes Chromium CDP metrics and DOM count, host free memory/load average, and Node process memory/CPU counters sampled on successful navigations. Windows load-average zeros are platform limitations; Node is the load generator, and no server CPU attribution is implied. Optional root-runner Docker/process telemetry may accompany the attachment but must identify its source and sampling interval.

Acceptance requires zero reader/navigation failures, all 20 navigations, both readers active into the final 15 seconds, pacing checks, minimum duration, exact before/after preservation and a passing process exit. Request counts vary with response duration; there is no invented fixed-count target, SLA threshold or capacity claim. This provides bounded local synthetic MariaDB evidence only.

Harness validation

The fixture author ran the following without launching services, browsers, builds or the long workload; both exited 0:

# From repository root
rtk node docs/redesign/phase-9/p9-requal-01/performance/metrics.mjs --self-test
# From job-tracker-ui
rtk node node_modules/typescript/bin/tsc --noEmit --skipLibCheck --strict --allowJs --esModuleInterop --target es2023 --module esnext --moduleResolution bundler ../docs/redesign/phase-9/p9-requal-01/performance/playwright.config.ts ../docs/redesign/phase-9/p9-requal-01/performance/sustained.spec.ts

The dependency-free self-check exercises empty percentiles, exact percentile boundaries, exclusion/counting of HTTP and transport failures, reversed membership, missing/duplicate/substituted IDs, and the fixed duration/pace constants. Strict TypeScript validates the fixture and inherited configs; this is harness validation, not workload evidence.

Actual results

Actual exclusive workload: 2026-10-24 13:10:23.274–13:25:23.280UTC, monotonic duration 900006.3119ms (required900000). Both readers completed1691 attempts: 3382 total, zero failures. All20 navigations passed; maximum observed readiness1686.51ms. Preflight passed and is excluded from workload counts.

Endpoint Attempts p50ms p95ms p99ms Maxms
All readers 3382 23.84 33.24 41.67 162.16
Application stats 846 22.43 27.80 34.03 57.79
Board 846 23.20 32.73 37.26 67.44
Career Profile 846 28.56 38.70 46.45 50.73
Documents 844 23.09 31.26 39.36 162.16

The20 workload telemetry samples observed minimum host free memory13024960512bytes (12.13GiB) and maximum sampled load-generator NodeRSS478834688bytes (456.65MiB). These are sampled host/load-generator measures, not server CPU attribution or proof of the true between-sample peak. Windows load averages are unsupported zeros. Chrome CDP/DOM/heap and full per-request measurements remain in the attachment. No capacity/SLA claim is made.

Independent SQL snapshots matched exactly for the250 unique application IDs, owned/deleted/global-tenant counts, complete canonical profile JSON/revision, Identity projection JSON and history count. Full API profile and Board membership checks also passed. This is equality of the stated selected invariants, not a whole-database byte comparison or power-loss test. Cleanup verified the generated schema absent.

Accepted evidence: .artifacts/p9-requal-01/performance/result.json, performance.json, performance-exit.json and retained trace/attachment. The wrapper explicitly sets the root performance.json reporter path. Earlier setup/preflight failures remain separately archived and contribute zero successful timed runs. The canonical API-vs-storage setup comparison follows StructuredCvProfileJson.SerializePersisted null-property omission; exact SQL before/after equality, full API comparison and CV null-as-inherit contracts remain intact.