Skip to content

Spec 010 T066: the analysis report PDF to pdf-export (pdf-export spec 002 T018, T021) - #960

Merged
adamjohnwright merged 2 commits into
mainfrom
spec010/t021-report-to-pdf-export
Nov 14, 2026
Merged

adamjohnwright merged 2 commits into
mainfrom
spec010/t021-report-to-pdf-export

Conversation

@adamjohnwright

Copy link
Copy Markdown
Contributor

The website's analysis report PDF, GET /AnalysisService/report/…, answered by pdf-export instead of the AnalysisService. This is pdf-export spec 002 T018 and T021, done here as spec 010 T066 (Story 6, the analysis gateway) with a new FR-025.

What changes

The analysis gateway (tools/analysis-gateway/gateway.ts)

  • GET (and HEAD) /AnalysisService/report/… goes to pdf-export, a second upstream (REPORT_UPSTREAM, default 127.0.0.1:4370). It is not queued: the report lane and REPORT_LIMIT are gone. Every other request still goes to the AnalysisService.
  • PER_CLIENT is kept. A client's reports in flight count towards it, and a report past it is refused (503, never queued). A reader who leaves a report gives its place back.
  • pdf-export is told the client in X-Reactome-Client, set to the gateway's own clientOf (an IPv6 client by its /64). Any value the request sent is removed.
  • When pdf-export can't be reached, the answer is 503 in the analysis service's JSON form, as pdf-export writes its own 503 (Retry-After, no-store, CORS). The AnalysisService's 502 is unchanged.
  • /health now reports reports: { upstream, active } in place of the report lane.

nginx (routes-core.conf): /AnalysisService/ sets X-Reactome-Client $remote_addr, overwriting any incoming value. The routes are unchanged, so the dev proxy and nginx tables still agree (routes.spec.ts).

Compose and the image (T018)

The "PDF Result" button opens the report's address in a new tab. Before, the page fetched and saved it, which would save pdf-export's "being made" page as report.pdf. ManagedDownloadDirective takes [crManagedDownload]="false" to leave a link to the browser.

The register (documentation/declared-differences.md): the report's status moves to "website routed". New rows:

  • the gateway: the report sent to pdf-export unqueued; 503 when it can't be reached; HEAD answered 405 by pdf-export.
  • the report: today's timing sent to a reporting service (in spec 002's Assumptions but missing from the register); the button opening in a tab.

Tests, each seen failing

  • Gateway (gateway.spec.ts), 7 new tests against a stand-in pdf-export. Seven mutations, each caught:
    • the client header not stripped
    • the client named from its own header
    • no share for reports
    • unreachable answered as busy
    • leaving doesn't end the call
    • reports sent to the AnalysisService
    • HEAD not sent to pdf-export
  • nginx (deploy/nginx/test-config.sh): after nginx -t, each deployment's image runs against a stand-in analysis upstream in a namespace with no network. A request sending X-Reactome-Client, X-Real-IP, X-Forwarded-For and CF-Connecting-IP naming another client must reach it named by its own address. With the directive removed it fails on all three deployments (client=203.0.113.9); with it, all pass.
  • Compose (compose.spec.ts): the tmpfs, PDF_EXPORT_WORK and REPORT_UPSTREAM checks fail on main's compose.
  • The button (e2e/analysis-results.spec.ts, "the result files download"): with the report stubbed, clicking "PDF Result" opens a tab at the report's address, the page fetches nothing and nothing downloads. Without the change, no tab opens (timeout). This is folded into that test, which has its own recording. A new test would need a new recording, which I could not take here.

Compared on the development host

These ran on loopback only, with no public host, production service or ReactomeGSA involved. pdf-export serve ran at 55cde47 from source on the private release 98 graph, behind this branch's gateway, against this host's own AnalysisService. The token was made as R5/R9 describe: seven gene symbols and two made-up identifiers.

  • pdf-export's ci/replay.ts, AnalysisService against the gateway path, over T001's error cases: 11 cases, 9 the same, 2 the listed differences (a malformed token, one holding %2F), 0 others. Call 4's refusals matched the stub.
  • Raw bytes of the same nine non-listed cases: status, Content-Type, Content-Disposition, CORS and body were identical, with the 400's timestamp masked.
  • End to end: one report (number=1) through the gateway answered 200 application/pdf, report.pdf, 11 pages, in 17 s. The working folder was empty afterwards.
  • The gateway's own 503, with pdf-export unreachable, as above.
  • T100's check at the new pin: an event PDF from pdf-export, with and without the token, 200 application/pdf.

To deploy (beta)

  1. docker compose build pdf-export analysis-gateway (pdf-export rebuilds at the new pin).
  2. docker compose up -d pdf-export analysis-gateway: pdf-export gets its tmpfs and PDF_EXPORT_WORK, and the gateway gets REPORT_UPSTREAM. REPORT_LIMIT is no longer read, so drop it from .env if it's set there. Nothing else in .env changes.
  3. nginx: docker compose build nginx && docker compose run --rm nginx nginx -t && docker compose up -d nginx, for the new header.
  4. Rebuild and serve the site for the button.
  5. Check: /health on 4350 shows reports.upstream at 4370, and a report from the site opens in a tab and downloads.

Production and release nginx still send /AnalysisService/ to Tomcat directly, so their reports stay Java's until the gateway runs there.

🤖 Generated with Claude Code

adamjohnwright and others added 2 commits November 14, 2026 03:05
… 002 T018, T021)

The analysis gateway sends GET (and HEAD) /AnalysisService/report/... to
pdf-export, a second upstream (REPORT_UPSTREAM), unqueued: the report lane
and REPORT_LIMIT are gone. A client's reports in flight count towards
PER_CLIENT and are refused past it; a reader who leaves gives its place
back. pdf-export is told the client in X-Reactome-Client, set to the
gateway's clientOf over anything the request sent, and a pdf-export that
cannot be reached is a 503 in the analysis service's JSON form. Everything
else still goes to the AnalysisService.

nginx sets X-Reactome-Client from the client's address on /AnalysisService/,
and test-config.sh now runs each deployment's image against a stand-in
upstream to show a request naming another client is still named by its
address (seen failing without the directive).

pdf-export pinned to 55cde47 (its T020 replay, T026, T027); its printer's
working folder a tmpfs owned by its user (PDF_EXPORT_WORK); still loopback
only; mem_limit 3g for the kept reports. The "PDF Result" button opens the
report's address in a new tab instead of fetching and saving it.

The register gains the gateway's three report rows and the report's two
missing ones; spec 010 gains FR-025 and T066.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@adamjohnwright
adamjohnwright merged commit 6843a33 into main Nov 14, 2026
8 checks passed
@adamjohnwright
adamjohnwright deleted the spec010/t021-report-to-pdf-export branch November 14, 2026 03:42
adamjohnwright added a commit to reactome/pdf-export that referenced this pull request Nov 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant