Story: Fix jetstream_admin missing gzip decompression
Table of Contents
This page documents a story in Sprint 24. It captures the goal, current status, acceptance criteria, and the tasks that compose it.
Goal
Split out of Fix image-batch NATS payload overflow, add SVG compression once that story's core goal (compression + byte-size-aware batching) shipped: the one remaining loose end, raised non-blocking in PR #1706 review, doesn't belong under a now-closed story.
jetstream_admin::peek_message() and peek_last_message()
(projects/ores.nats/src/service/jetstream_admin.cpp) read
natsMsg data directly without extracting headers or calling
decompress_if_flagged(), unlike extract_message() in
client.cpp. Since js_publish() now transparently gzips payloads
at or above the 4096-byte threshold, any JetStream message that
crosses it (e.g. an image-batch workflow message) shows up as raw
gzip bytes in admin tooling such as ores.qt's QueueDetailDialog.
Fix by extracting headers the same way extract_message() does,
then running data through decompress_if_flagged() before returning
stream_message.
Status
| Field | Value |
|---|---|
| State | DONE |
| Parent sprint | Sprint 24 |
| Now | Nothing. |
| Waiting on | Nothing. |
| Next | Nothing. |
| Last touched | 2026-07-29 |
Acceptance
[X]peek_message()andpeek_last_message()extract headers and calldecompress_if_flagged()before returningstream_message, same asextract_message().[X]A JetStream message above the 4096-byte compression threshold (e.g. an image-batch workflow message) displays decompressed in admin tooling (ores.qt'sQueueDetailDialog), not as raw gzip bytes.
Tasks
| Task | State | Start | End | Description |
|---|---|---|---|---|
| Decompress payloads in jetstream_admin peek_message/peek_last_message | DONE | 2026-07-29 | 2026-07-29 | jetstream_admin::peek_message() and peek_last_message() (projects/ores.nats/src/service/jetstream_admin.cpp) read natsMsg data directly without extracting headers or calling decompress_if_flagged(), unlike extract_message() in client.cpp. Since js_publish() now transparently gzips payloads at or above the 4096-byte threshold, any JetStream message that crosses it (e.g. an image-batch workflow message) will show up as raw gzip bytes in admin tooling such as ores.qt's QueueDetailDialog. Fix by extracting headers the same way extract_message() does, then running data through decompress_if_flagged() before returning stream_message. Raised in PR #1706 review, explicitly non-blocking for that PR. |
Decisions
Shared helper, not inline duplication
Decided in the decompress task. Added a
fill_data_and_headers() helper in jetstream_admin.cpp's anonymous
namespace, mirroring client.cpp's extract_message(), rather than
inlining the header-extraction + decompress_if_flagged() logic
twice (once in peek_message(), once in peek_last_message()).
jetstream_admin has no existing unit-test coverage (live-JetStream-
only, exercised via manual QA), so no new unit test was added; local
build and the existing ores.nats.tests suite both pass.