Optional individual thread factories for reader and writer#1583
Conversation
|
@claude review |
|
Claude finished @scottf's task in 3m 5s —— View job PR Review: Optional individual thread factories for reader and writer
SummaryThis PR adds optional Strengths
Observations1. "Restarted across reconnects" wording is slightly misleading
The executor itself is not recreated on reconnect — This matters for virtual-thread users: 2. Shared-Options scenario silently shares the reader/writer executor 3. No 4. Integration test could assert thread names more precisely assertFalse(readerFactory.created.isEmpty());
assertFalse(writerFactory.created.isEmpty());This confirms the factory was invoked, but it would be marginally stronger to also assert that the created thread names start with the expected prefix (the factory already records names): assertTrue(readerFactory.created.stream().anyMatch(n -> n.startsWith("test-reader")));
assertTrue(writerFactory.created.stream().anyMatch(n -> n.startsWith("test-writer")));Not a blocker — the current test catches the main regression (factory not used at all). 5. No reconnect-path coverage Minor / Nits
Overall this is a solid, focused addition. The two docstring points (reconnect semantics and shared-Options behavior) are the most worth addressing before merge. |
|
@claude re-review with these notes:
Simplified comments
Addressed with notes in readme since this is an options wide behavior
This is intentional. An executor service would provide a pool.
No, I think this is the correct behavior.
There are many tests that test reconnect, so this review point is not correct.
Fixed
Correct. Clarity not needed. |
|
Claude finished @scottf's task in 3m 5s —— View job PR Re-Review: Optional individual thread factories for reader and writer
Re-Review SummaryEach point from the previous review is addressed. The "address review comments" commit (3293e6d) is clean — a few notes below. Previous Points — All Addressed1. Reconnect wording — Simplified to just "Sets a custom thread factory used to run the connection's reader/writer." Clean, no misleading claims. 2. Shared-Options behavior — The README's new "Connection Options Executors" section explains this well. Additionally, the implementation itself improved: 3. No ExecutorService variant (noted as intentional) — The PR actually added 4. Integration test assertions — Confirmed, checking 5. Reconnect coverage — Fair point; the existing reconnect suite covers the path. 6. 7. One New ObservationThe follow-up commit added However, these new APIs have no test coverage. SummaryImplementation is solid. The lifecycle logic, README explanation, and executor-per-task fix for shared-Options are all good additions. The only gap is tests for the new |
|
@claude added some coverage, please review |
|
Claude finished @scottf's task in 1m 56s —— View job PR Review: New ExecutorService Test Coverage
Review SummaryThe "more unit tests" commit ( New Coverage in
|
| Behavior | Assertion | ✓ |
|---|---|---|
| Builder method wires executor directly | assertSame(es, options.getReaderExecutor()) |
✓ |
| Lifecycle flag is correct (caller owns it) | assertFalse(options.readerExecutorIsInternal()) |
✓ |
| Copy constructor propagates the user executor | assertSame(es, copy.getReaderExecutor()) |
✓ |
| Copy also has correct lifecycle flag | assertFalse(copy.readerExecutorIsInternal()) |
✓ |
The try/finally wrapping es.shutdownNow() is the right pattern — avoids leaking a thread pool on assertion failure.
New Coverage in NatsConnectionImplTests.java
The verifyExternalExecutors helper is extended with userReaderEs / userWriterEs parameters and now asserts:
options.getReaderExecutor()returns the same instance passed by the caller (checked while the connection is live)readerExecutorIsInternal()is false- The user-supplied executor is not shut down immediately after connection close — the "caller owns lifecycle" contract is enforced against a real connection, not just Options in isolation
The critical assertion at NatsConnectionImplTests.java:205 (after nc is closed):
// user supplied reader/writer executors must NOT be shut down by the connection (caller owns them)
if (userReaderEs != null) {
assertFalse(userReaderEs.isShutdown());
}This is exactly the right place to make this assertion, and the comment makes the intent clear.
Minor Notes
assertEquals(options.getReaderExecutor(), userReaderEs)inside the helper will fall back to reference equality sinceExecutorServicedoesn't overrideequals()— functionally identical toassertSame. Consistent with howconnectEsis checked in the same helper, so no issue here.- The tests appropriately use
newCachedThreadPool()forreaderEs/writerEs(unbounded, so no deadlock risk when the reader's long-lived task is submitted to it). Correct choice.
Verdict
All three previously untested behaviors — builder method, copy constructor propagation, and lifecycle ownership — are now covered both at the unit level (OptionsTests) and against a real connection (NatsConnectionImplTests). The new tests are well-structured and follow established patterns. This is ready to merge.
| } | ||
|
|
||
| def jarVersion = "2.60.0" | ||
| def jarVersion = "2.26.0" |
There was a problem hiding this comment.
Is it expected that this has gone down?
There was a problem hiding this comment.
This was a mistake and is being fixed here.
No description provided.