Skip to content

Topic event published during a republish is no longer lost - #6834

Open
TIVMOF wants to merge 10 commits into
eclipse-dirigible:masterfrom
TIVMOF:fix/lost-events
Open

Topic event published during a republish is no longer lost#6834
TIVMOF wants to merge 10 commits into
eclipse-dirigible:masterfrom
TIVMOF:fix/lost-events

Conversation

@TIVMOF

@TIVMOF TIVMOF commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

This PR:

Problem

Client-Java topic subscriptions were non-durable, and ListenerClassConsumer.register() tears every subscription down before re-registering it. A non-durable subscriber receives only what is published while it is connected, so every event raised inside that window was discarded — while the producer sent it PERSISTENT, paying for persistence a non-durable subscriber cannot collect.

An operator republishes at 14:32. A record created by an integration at 14:32:01 lands in the teardown window: the repository publishes the create event, nothing is subscribed, the message is gone. That record never starts its process, resolves its register or posts its document, and is indistinguishable from one the automation legitimately had nothing to do for.

Change

Topics are now opened with createDurableSubscriber under a client id derived from the handler's label and the tenant-resolved destination, so the broker holds their messages until the handler reconnects. The id must be stable — a varying one would open an empty subscription on every reload and strand the previous one's backlog — which is what the derivation and its test pin down.

Queues are deliberately untouched: a queue already retains messages for an absent consumer.

ActiveMQConnectionArtifactsFactory gains a client-id overload, since JMS forbids setting a client id on a started connection and the existing createConnection starts it.

Cleanup is the broker's job

A durable subscription outlives its subscriber by design, so nothing reclaims one whose handler was deleted rather than reloaded. That cannot be fixed in the consumer: JavaLoader.applyGeneration builds its unload set from the removed and the replaced FQNs, so onClassUnloaded fires on a republish exactly as on a deletion — unsubscribing there would destroy the subscription this change exists to preserve. A class deleted while the server was down is never reported at all, since the previous generation starts empty.

So the reclaim is declarative: offlineDurableSubscriberTimeout (7 days) in MessagingConfig, generous enough that no restart or republish can expire a subscription that is about to reconnect.

Note on the restart case

The broker is embedded (vm://localhost), so during a JVM restart there is no producer either — the publishers are generated repositories in the same JVM. Nothing is lost at restart because nothing is being sent. The republish window, where the JVM stays up and other writers keep going, is the one that matters.

Trade-off

A topic's messages now accumulate in the broker's store (SystemDB) while a handler is down, instead of being discarded. That is the point of the change, but it means a handler left broken or undeployed grows the store until the sweep reclaims its subscription. Documented in engine-java/CLAUDE.md alongside the stable-id requirement and the unload-hook reasoning.

Testing

Four new tests in ListenerClassConsumerDurabilityTest — there was no topic coverage at all before, so this path was entirely unverified. Verified red-first: with the change stripped, two fail with a durable subscription needs the connection to carry a client id ==> expected: not <null>.

Green: engine-java 98/98, engine-listeners 51/51 (the JavaScript listener path is unaffected). Two existing tests needed their createConnection stub widened to the two-arg call — mock maintenance from the signature change, no assertion altered.

🤖 Generated with Claude Code

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.

Client-Java topic subscriptions are non-durable - events published during restart or republish are lost

2 participants