Skip to content

Port /data/orthology and /data/orthologies to node; 405 and RFD header on every ported endpoint - #477

Merged
adamjohnwright merged 2 commits into
mainfrom
port/orthology
Oct 15, 2026
Merged

adamjohnwright merged 2 commits into
mainfrom
port/orthology

Conversation

@adamjohnwright

Copy link
Copy Markdown
Contributor

The species selector's two orthology calls now come from node:

  • GET /data/orthology/{id}/species/{speciesId}: one object's counterpart in a species.
  • POST /data/orthologies/ids/species/{speciesId}: up to twenty ids, as a map.

graph-core's Cypher runs as written, and the domain serialiser writes each object in Java's views.

Matching Java

Everything below was measured against Java and is covered by a test:

  • Species. It is a Spring Long path variable. Hex, +, leading zeros and spaces anywhere are accepted. A blank species is Java's 500 "converted to null"; any other bad value is a 400 naming the text. The Integer parsers now take a bit width, so Long shares their code.
  • GET errors.
    • An id that is neither a stable id nor a dbId is a 404 naming it.
    • An id with no counterpart is the controller's 500 with a null message.
    • A dbId past a long is a 500.
  • POST checks, in Java's order: the content type (415, with MimeTypeUtils' messages), then the species, then the body (422).
  • POST body.
    • It is split on , ; \n \t the way String.split does it.
    • Past twenty ids, the first twenty go into a HashSet.
    • The answer is written in Java's HashMap order; JavaHashMap reproduces it, resizes included.
    • writeDomain can now write a map, so @id numbering runs across the values, as Jackson does in one write.
  • Declared difference: . is not found here; Java's split throws a 500.

Two gaps on every ported endpoint

  • nginx sends every method to node, and until now a POST to a GET route got Express's HTML 404. It now gets Java's 405 envelope.
  • Spring adds Content-Disposition: inline;filename=f.txt when the last segment ends in an extension it does not trust. That includes a versioned id such as R-HSA-69620.5. rfd-snapshot.json holds the trusted extensions, generated from the deployed spring-web and Tomcat tables by snapshot-rfd.mjs.

Checked

  • Against Java on a local node: 52 cases, covering GET, POST, every error, the views, JSOG, more than twenty ids and the 405s. All are identical apart from where one header sits in the list.
  • Diff harness: it now fills a second path variable and sends POST bodies.
  • Mutation checks: each new test fails under a mutation of the code it covers. Examples: map in insertion order, no resize, trailing empties kept, any content type, a 32-bit species, no 405.

🤖 Generated with Claude Code

adamjohnwright and others added 2 commits October 15, 2026 16:13
…r everywhere

The species selector's two orthology calls now come from node:
GET /data/orthology/{id}/species/{speciesId} and POST
/data/orthologies/ids/species/{speciesId}. graph-core's two Cypher
queries are run as written (inside a subquery, so the first row is
Java's first) and each object is written alone by the domain serialiser.

What Java does, all measured, all reproduced:
- the species is a Spring Long path variable: hex, '+', leading zeros
  and spaces anywhere accepted; a blank one is the 500 "converted to
  null"; the rest a 400 naming the text. The Integer parsers now take a
  bit width, so Long shares them.
- an id that is no id is a 404 naming it; one with no counterpart is the
  controller's 500 with a null message; a dbId past a long is a 500.
- the POST checks the content type (415, MimeTypeUtils' messages), then
  the species, then the body (422). It splits on , ; newline and tab as
  String.split does, keeps the first twenty in a HashSet, and writes a
  HashMap -- JavaHashMap reproduces its iteration order, resizes
  included. writeDomain gains a map, so @id numbering runs across the
  values as Jackson's does in one write.

One declared difference: '.' is not found, where Java's split throws.

Two gaps on every ported endpoint, found here:
- nginx sends every method to node, and a POST to a GET route got
  Express's HTML 404; it is Java's 405 envelope now.
- Spring marks a body inline;filename=f.txt when the last segment ends in
  an extension it does not trust -- a versioned id, R-HSA-69620.5,
  included. rfd-snapshot.json holds the trusted ones, from the deployed
  spring-web and Tomcat tables (snapshot-rfd.mjs).

Against Java on a local node: 52 cases (GET, POST, errors, views,
JSOG, over twenty ids, 405s) identical but for where one header sits;
the diff harness learns a second path variable and POST bodies. Every
new test failed under a mutation of the code it covers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review of #477, four defects, each now matching Java:
- getOrthologies puts an id in its map only when it is an id; node put
  the non-ids too, which grew the table and reordered the answer
  (R-HSA-69620.11,R-HSA-69620.9 and eleven non-ids: Java's .11 first).
  orthologyMap builds the two maps as Java does.
- the body is decoded as the JDK decodes it for Latin-1, ASCII and the
  UTF family -- UTF-16 big-endian without a mark, UTF-32 at all, a
  reversed mark or a lone surrogate as U+FFFD -- where TextDecoder read
  UTF-16 little-endian, ASCII as windows-1252, and refused UTF-32.
  44,000 random bodies over 55 charset names against the JDK's
  new String(bytes, charset): identical.
- JavaHashMap ports HashMap's put, resize and tree bins: eleven ids
  sharing a hash come out in the JDK's order. 10,000 key sets against
  java.util.HashMap, 3,410 of them with tree bins: identical.
- the body is read as it came: not inflated, as Tomcat does not.

Also from the review: the queries run one at a time, as Java's do, on
the database the site shares. Against Java: those cases, UTF-16, UTF-32,
gzip, ASCII and thirteen colliding ids -- identical. Each new test fails
under a mutation of the code it covers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@adamjohnwright
adamjohnwright merged commit b1dab2c into main Oct 15, 2026
6 checks passed
@adamjohnwright
adamjohnwright deleted the port/orthology branch October 15, 2026 17:05
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