You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(server): cache the optimized parquet route like the flat one (#3894)
Closes#3889.
`POST /api/v1/parse/parquet/optimized` re-parsed on every request because the response shape had no cache key. It now has two, `{seed}-parquet-optimized-v1` for the body and `{seed}-parquet-optimized-metadata-v1` for the `X-IFC-Metadata` header stored verbatim, so a replay reports the same `optimization_stats` the live parse did. The namespace is separate from `-parquet-v5`, so a cached flat response never satisfies the optimized route and vice versa. The handler moves to its own module so `parquet.rs` stays under the ratchet.
Three design points on the record: the write is synchronous rather than backgrounded, because a background write races the very next request and this is the small payload; a hit also requires the symbolic sidecar, since the optimized parse writes it and replaying past a missing one would leave `GET /parse/symbolic/{key}` polling a key nobody writes; and a truncated or orphaned cached blob degrades to a miss with a warning instead of a 500 on every later request.
Tests: a second identical request replays without parsing (a sentinel written over the cached body comes back), flat-cached does not satisfy optimized and vice versa with anti-vacuity checks, a missing sidecar re-parses and writes one, a body without metadata re-parses, a different file does not read the first file's entry, and key uniqueness across all suffixes. Both keys documented in docs/guide/server.md and cache_keys.rs.
Not verified against a live server or the 57.9 MB file from the issue; what is proven is that the second request does not parse. Gates on the head: `cargo test -p ifc-lite-server` 0 (246 passed), clippy -D warnings 0, module_size_ratchet 6/6, check-module-size 0, check-changesets 0. Changeset: `@ifc-lite/server-bin` minor.
`POST /api/v1/parse/parquet/optimized` is now cached, so a repeat request is a disk read instead of a full re-parse (#3889). The route was added without a cache key of its own, which left the two Parquet endpoints with opposite properties: the flat route stored its large payload and replayed it, while the optimized route rebuilt its small payload on every request, and got no benefit from a flat response cached seconds earlier either. On a 57.9 MB file the flat route roughly halved on its second call and the optimized route did not improve at all.
6
+
7
+
The optimized response now has its own key pair, `{sha256}-{filter}-parquet-optimized-v1` for the body and `{sha256}-{filter}-parquet-optimized-metadata-v1` for the `X-IFC-Metadata` header, `optimization_stats` included, so a replay reports what the live parse reported. They are a separate namespace from the flat route's `-parquet-v5` / `-parquet-metadata-v4` on purpose: the optimized payload is quantized and deduplicated, so a cached flat response must never satisfy the optimized route or the other way round. Bump the suffix on any change to the optimized payload's columns.
8
+
9
+
Two details of the write. It happens before the response goes out rather than in a background task, because this payload is the small one and a background write races the very next request, which is the request the cache exists to serve. And a hit requires the symbolic sidecar to still be present alongside the body and metadata: the optimized parse is what writes that sidecar, so replaying past a missing one would leave `GET /api/v1/parse/symbolic/{cache_key}` polling a key nobody writes.
0 commit comments