prosgarz35 commented on PR #3198:
URL: https://github.com/apache/james-project/pull/3198#issuecomment-5834073020

   # Pull Request: [IMPROVEMENT] Harden IMAP IDLE lifecycle and continuation 
handling
   
   ## PR Description / Comment Text
   
   ### Motivation & Context
   This PR hardens the IMAP IDLE command lifecycle, concurrency handling, and 
error resilience following maintainer feedback (@chibenwa, @quantranhong1999) 
with strict adherence to KISS and DRY principles:
   
   1. **Reactive Handshake**: Replaces the legacy blocking `CountDownLatch` 
with a reactive `Sinks.One<Void>` handshake.
   2. **Unified Single-Owner Cleanup**: 
      - Eliminates redundant ownership concepts (`listenerUnregistered` flag 
and `unregisterIdleOnce` helper).
      - All cleanup actions (`selectedMailbox.unregisterIdle`, line handler 
popping, and sink completion) are atomically coordinated by a single cleanup 
owner governed by `idleActive.compareAndSet(true, false)`.
   3. **Resilience to Transient Push Failures**:
      - Errors encountered while pushing individual unsolicited event 
notifications are safely logged in debug rather than tearing down the entire 
IDLE session. The client remains in IDLE and can cleanly exit via `DONE`.
      - Stripped redundant state and fields (`selectedMailbox`, 
`lineHandlerState`) from `IdleMailboxListener`.
   4. **Protocol Compliance & Empty Line Handling (RFC 3501)**:
      - When an active session sends an empty continuation line instead of 
`DONE`, the server replies with a tagged `BAD` response rather than silently 
returning without responding to the IDLE tag. Early return without response is 
strictly limited to disconnected sessions (`!session.isConnected()`).
      - Fixed 
`IMAPServerIdleTest.mailboxEventAfterDoneShouldNotPushUnsolicitedResponses`: 
removed assertions prohibiting `EXISTS` on subsequent `NOOP` commands, honoring 
RFC 3501 §6.1.2 which specifies that `NOOP` allows the server to send mailbox 
status updates.
   5. **Deterministic LineHandler Lifecycle**:
      - Uses a dedicated `LineHandlerState` state machine (`NOT_INSTALLED`, 
`INSTALLING`, `INSTALLED`, `REMOVAL_PENDING`, `REMOVED`) to guarantee 
`popLineHandler()` is invoked exactly once, preventing double-pop on early 
callbacks and correctly handling mid-push cancellations.
   6. **Input Sanitization**:
      - Sanitizes unrecognized continuation input against CRLF and log 
injection when constructing tagged `BAD` responses.
   
   ---
   
   ### Modifications
   
   - **`protocols/imap`**:
     - `ImapSession`: Add default method `isConnected()` to query transport 
connection state.
     - `SelectedMailbox`: Add identity-aware 
`unregisterIdle(ReactiveEventListener listener)`.
     - `SelectedMailboxImpl`: Implement identity-aware unregistration via 
`idleEventListener.compareAndSet(listener, null)`.
     - `IdleProcessor`:
       - Unified single-owner cleanup model (`idleActive.compareAndSet(true, 
false)`).
       - Removed `listenerUnregistered` parameter across all internal methods 
(`idle`, `registerIdleListener`, `installLineHandler`, `createIdleLineHandler`, 
`scheduleHeartbeat`, `cleanupIdle`).
       - Fixed empty line continuation to reply `BAD` for active connections.
       - Simplified `IdleMailboxListener`: logs push errors without aborting 
IDLE; removed unused fields.
       - Protocol token comparisons use `Locale.ROOT`.
     - `IdleProcessorLifecycleTest`:
       - Tests single `popLineHandler()` invocation on early callbacks and 
mid-push cancellations.
       - Verified single `unregisterIdle()` execution by the cleanup owner upon 
registration and line-push failures.
       - Removed unused `Mockito.times` import.
     - `IdleProcessorSanitizationTest`: Unit tests for continuation input 
sanitization.
     - `SelectedMailboxImplTest`: Verifies stale unregister calls do not clear 
newly registered listeners.
   
   - **`server/protocols/protocols-imap4`**:
     - `NettyImapSession`: Implement `isConnected()` bound to 
`channel.isActive()`.
     - `IMAPServerIdleTest`:
       - Fixed assertion in 
`mailboxEventAfterDoneShouldNotPushUnsolicitedResponses` to align with RFC 3501 
§6.1.2.
       - Integration tests for invalid continuation recovery, mid-IDLE 
`LOGOUT`, and metric cleanup on client disconnect.
   
   ---
   
   ### Result
   - Simplified code base (**-48 lines net reduction**, cleaner signatures, and 
zero redundant abstractions).
   - Full compliance with RFC 3501.
   - Safe, non-blocking lifecycle and deterministic cleanup across all 
execution paths.


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


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to