Skip to content

2026.09.15 — 2026-09-08

Added

  • Rebuild the console around the result, and keep queries out of URLs (5a083c1f)

    Execution is now POST-then-stream. The query text goes in a request body and the stream is opened by a short-lived, single-use reference. An EventSource can only issue a GET, so until now an operator's predicates — and the values they were searching for — were written into every proxy access log on the path, and a long query hit a URL length limit. A query that can be judged before it runs is now refused by the POST, where a status code carries a body the caller can read; anything the stream itself refuses still arrives as a failed frame.

    The screen is laid out for an incident. A resizable editor pane sits above a results pane that owns the rest of the viewport, so the rows stay on screen. The stack of up to five full-width alerts is gone: everything they said is in one meta bar with a disclosure, in full, and none of it pushes the data below the fold. A running static query can be stopped, not just a tail.

    A tail can now be paused without being stopped — the broker is still being read, the view is just held, with a count of what is waiting — and scrolling away from the head of a live feed pauses it for you rather than moving the rows under you.

    A captured tail states the stronger claim, and only when every target is captured on the node it is read from. One node without a tap and it is a sampled tail again, with the gap named. Per row, provenance is three words rather than two: live, sampled, captured.

  • Full-text search over stored message bodies (78f91aaa)

    MATCH (body) AGAINST ('order 4471') searches the stored bodies in the message index from a GIN index rather than by scanning, and ORDER BY match_rank sorts by how well each row matched. Quoted phrases, -exclusion and or work the way they do in a search box, and a malformed query is a no-match rather than an error.

    Index only. There is no selector a broker could evaluate for this and no honest approximation of one, so a MATCH against broker."..." is refused by name rather than silently meaning something else. match_rank without a MATCH to rank against is refused for the same reason.

    The simple text configuration, not english: message bodies are identifiers, JSON and codes, and English stemming maps orders to order while leaving 4471 alone — which corrupts exactly the lookups this exists for. Binary bodies are not indexed at all, because a tsvector over base64 is garbage tokens and index bloat for no retrieval value; use LIKE for those, which is unchanged.

    Three new index-only columns come with it: origin, origAddress and sourceMessageId.

    The spelling is MATCH (body) AGAINST ('terms') rather than the two-argument MATCH(body, 'terms') this was designed with. MATCH is a reserved word in the SQL grammar the parser implements and the comma form cannot be parsed at all — measured, not assumed — so the dialect takes the grammar's own form instead of forking a parser.

    See ADR-0063.

  • Capture every message an address routes, not just what a poll saw (8bde177e)

    The message index and the live tail both worked by browsing a queue every few seconds and recording what was sitting on it. A queue that drains faster than that interval is invisible to both — which is most healthy queues, most of the time, and the reason the index only ever seemed to fill up with expired messages.

    Capture closes that gap. Set a subscription's mode to CAPTURE and Studio installs a non-exclusive divert on every live node, copying everything the address routes into a ring-bounded queue it owns and drains over the Core protocol. A message produced and consumed in the same millisecond is still there to query afterwards, by its original queue name.

    Turning it on needs the new capture:write permission. It is deliberately not settings:write: capture mutates broker routing on a schedule and creates a second copy of production payload, which is a different authority from changing how often Studio polls. Every install and removal is audited before the broker call and updated with the outcome.

    Bounded by construction, because Studio must never be why a broker falls over: ring-size makes the broker drop the oldest rather than grow, address-full-policy=DROP keeps it from blocking or paging, an expiry-delay with auto-create-expiry-resources=false bounds an abandoned tap in age as well as in size, and a per-message body cap keeps a large message out of Postgres. A security-setting restricts the capture queue to Studio's own broker role, and capture is refused outright if that cannot be set — an unguarded second copy of production traffic is not something to create by accident. It is also refused when an exclusive divert on the source address would shadow it, because that installs cleanly and captures nothing.

    None of these objects disappears on a broker restart. Deleting the subscription is what removes them; nothing else will. The screen says so before you start.

  • See and manage diverts across every node of a cluster (6ea8d1eb)

    The Routing view lists every divert and every bridge a cluster has, merged across nodes and attributed to the ones each was found on. A divert whose source, destination or filter differs on one node appears as two rows rather than one, because that divergence is the thing you opened the view to find.

    Diverts can be created and deleted, behind divert:write, with the same dry run, per-node outcome and audit record every other lifecycle operation has. Bridges stay read-only.

    Two things this deliberately does not claim. It never says where a divert came from: Artemis records nothing on a divert about whether it was declared in broker.xml or created over management, so any such badge would be a guess. What it does say is ownership, drawn from Studio's own records — a capture divert by its reserved name, an operator's divert from the audit trail.

    And a divert created here is not temporary. Diverts, address settings and security settings created over the management API survive a broker restart — measured on Artemis 2.56.0, and the opposite of what this project previously assumed. The hazard is therefore configuration drift, not evaporation: the running broker will disagree with the broker.xml your estate deploys from until you add it there, and nothing removes it for you. The create dialog says exactly that and hands you the snippet to paste.

    See ADR-0065.

Apache-2.0. Apache ActiveMQ and Apache ActiveMQ Artemis are trademarks of the Apache Software Foundation. Artemis Studio is an independent project, not produced by, endorsed by, or affiliated with the ASF.