reiabreu opened a new pull request, #8812:
URL: https://github.com/apache/storm/pull/8812

   Fixes #8810
   
   ## Problem
   
   `BatchInserter` held a **strong** `JCQueue queue` reference, and inserter 
instances live in **instance-field** `ThreadLocal`s on the same `JCQueue`. This 
creates a cycle that prevents the normal ThreadLocal weak-key expunge path from 
ever firing:
   
   ```
   Thread
     └─ ThreadLocalMap
          key (weak):    JCQueue.thdLocalBatcher     ← the ThreadLocal object
          value (strong): BatchInserter
                            └─ queue: JCQueue (strong)
                                   └─ thdLocalBatcher: ThreadLocal  ← key is 
now strongly reachable!
   ```
   
   The weak key in `ThreadLocalMap` becomes eligible for expunge only when it 
is *not* strongly reachable. Here it always is — via `value → queue → field` — 
so the entry is never cleaned up, and the `JCQueue` (recv queue, overflow 
queue, metrics, batch buffer) is retained for as long as the producer thread 
lives.
   
   In production this is harmless: Storm runs workers as dedicated JVM 
processes where threads and queues share a lifetime. In `LocalCluster`, 
embedded deployments, or test harnesses that repeatedly start/stop topologies 
on long-lived threads, each stopped topology can strand its `JCQueue` instances.
   
   ## Fix
   
   Store the `JCQueue` as a `WeakReference` inside `BatchInserter`. This cuts 
the `value → JCQueue` strong path:
   
   ```
   Thread
     └─ ThreadLocalMap
          key (weak):    JCQueue.thdLocalBatcher
          value (strong): BatchInserter
                            └─ queueRef: WeakReference → JCQueue   (no longer a 
strong path to the key)
   ```
   
   When the last external strong ref to the `JCQueue` is dropped, the 
`thdLocalBatcher` field (and therefore the `ThreadLocalMap` key) becomes 
weakly-reachable, and the entry is expunged on the next `ThreadLocal` access by 
the producer thread. `BatchInserter` is then released too.
   
   `flush()` and `tryFlush()` dereference the `WeakReference` once at entry and 
bail out silently if the queue was already collected (the topology is dead; 
in-flight tuples are already lost). `publish()` and `tryPublish()` need no 
changes — they only touch `currentBatch`.
   
   ## Note for PR #8796
   
   `DynamicBatchInserter` (introduced in #8796) extends `BatchInserter` and its 
own overrides (`batchSize()`, `afterFlush()`) never access `queue` directly, so 
this fix covers it automatically — no separate change is needed there.
   
   ## Test plan
   
   - [ ] `mvn test -pl storm-client -Dtest=JCQueueTest` passes
   - [ ] Optionally: reproduce with a `LocalCluster` that repeatedly 
submits/kills a topology and verify the `JCQueue` instances are no longer 
retained after kill
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)


-- 
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