Croway commented on PR #25558:
URL: https://github.com/apache/camel/pull/25558#issuecomment-5394164015

   Thanks for working on this! Testing the change I found a regression: the 
queue-reference release added on producer stop has no matching re-acquire on 
producer start. Stopping and restarting the producer route (route controller, 
JMX, supervising restart) permanently breaks the endpoint — in exactly the 
producer-only `discardIfNoConsumers=true` scenario this PR targets.
   
   **What happens:** `onStopped(SedaProducer)` now calls `onShutdownEndpoint`, 
which removes the `QueueReference` from `SedaComponent.queues`. On route 
restart, `onStarted` only re-adds the producer to the set — nothing 
re-registers the queue (the endpoint itself was never stopped, so 
`getOrCreateQueue` doesn't run again). The next send hits `getQueueReference()` 
→ `null` → throws.
   
   Reproducer (fails deterministically on this branch, passes on `main` with 
the seda changes reverted):
   
   ```java
   class SedaDiscardIfNoConsumersProducerRouteRestartTest extends 
ContextTestSupport {
   
       @Test
       void testSendStillWorksAfterProducerRouteRestart() throws Exception {
           // producer-only endpoint: sending works, message is silently 
discarded
           template.sendBody("direct:start", "discarded-1");
   
           context.getRouteController().stopRoute("producer");
           context.getRouteController().startRoute("producer");
   
           // FAILS on this branch:
           // SedaConsumerNotAvailableException: No queue available on 
endpoint: seda://bar?discardIfNoConsumers=true
           assertThatCode(() -> template.sendBody("direct:start", 
"discarded-2"))
                   .as("send after producer route restart should discard 
silently, not fail")
                   .doesNotThrowAnyException();
       }
   
       @Override
       protected RouteBuilder createRouteBuilder() {
           return new RouteBuilder() {
               @Override
               public void configure() {
                   
from("direct:start").routeId("producer").to("seda:bar?discardIfNoConsumers=true");
               }
           };
       }
   }
   ```
   
   A symmetric approach would likely solve it: have `onStarted(SedaProducer)` 
re-register the reference with the component (mirroring what `onStopped` 
releases), and do both under the component lock — `onShutdownEndpoint` 
currently mutates the `queues` HashMap unlocked, and this PR now invokes it 
from concurrent producer-stop paths.
   
   _Claude Code on behalf of @Croway_
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to