Skip to content

OF-3179 & OF-3180: Safe, ordered, and async ConnectionCloseListener execution#3140

Merged
akrherz merged 4 commits intoigniterealtime:mainfrom
guusdk:OF-3180_OF-3179_Connection-closure-improvements
Feb 16, 2026
Merged

OF-3179 & OF-3180: Safe, ordered, and async ConnectionCloseListener execution#3140
akrherz merged 4 commits intoigniterealtime:mainfrom
guusdk:OF-3180_OF-3179_Connection-closure-improvements

Conversation

@guusdk
Copy link
Member

@guusdk guusdk commented Feb 14, 2026

This PR ensures ConnectionCloseListeners run in a deterministic priority order (fixing OF-3179) and offloads all listener execution from Netty event loops (fixing OF-3180), preventing stale session state and thread starvation.

Key Changes:

  • OF-3179: Priority-based sequential execution (critical cleanup first, third-party last).
  • OF-3180: All listener invocations now run on a dedicated thread pool (ConnectionManagerImpl executor), protecting Netty threads from blocking operations.

Please see individual commit messages for additional details.

Expand the listener Javadoc to clearly document that a connection closure does not necessarily imply session closure. Add guidance warning implementers not to make this assumption and direct them to SessionEventListener for reliable session lifecycle events.
@akrherz
Copy link
Member

akrherz commented Feb 14, 2026

@gemini-code-assist please review

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates Openfire’s connection-close handling to execute ConnectionCloseListener callbacks deterministically (priority order) and off the Netty event loop, using a dedicated executor managed by ConnectionManagerImpl.

Changes:

  • Introduces a dedicated “connection event” ThreadPoolExecutor in ConnectionManagerImpl, including configurable system properties and JMX exposure.
  • Updates close-listener invocation to run sequentially by priority and to be offloaded to the new executor.
  • Adjusts built-in listeners to return already-completed futures and to declare built-in priority.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
xmppserver/src/main/java/org/jivesoftware/openfire/spi/ConnectionManagerImpl.java Adds a dedicated executor + async helper APIs, system properties, and JMX registration/unregistration.
xmppserver/src/main/java/org/jivesoftware/openfire/net/AbstractConnection.java Changes close listener storage and implements priority-ordered, executor-offloaded, sequential listener execution.
xmppserver/src/main/java/org/jivesoftware/openfire/SessionManager.java Updates built-in close listeners to run synchronously (on the offloaded executor) and assigns built-in priority.
xmppserver/src/main/java/org/jivesoftware/openfire/session/LocalComponentSession.java Updates component session close listeners to synchronous + built-in priority.
xmppserver/src/main/java/org/jivesoftware/openfire/net/ComponentStanzaHandler.java Updates extra-domain component close listener to synchronous + built-in priority.
xmppserver/src/main/java/org/jivesoftware/openfire/ConnectionCloseListener.java Adds priority concept (constants + default method) and clarifies semantics in Javadoc.
i18n/src/main/resources/openfire_i18n.properties Adds i18n strings for the new executor system properties.
i18n/src/main/resources/openfire_i18n_nl.properties Adds Dutch i18n strings for the new executor system properties.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@guusdk guusdk force-pushed the OF-3180_OF-3179_Connection-closure-improvements branch from 41303b1 to 8a0b927 Compare February 14, 2026 20:14
@guusdk
Copy link
Member Author

guusdk commented Feb 14, 2026

@copilot retest

@guusdk
Copy link
Member Author

guusdk commented Feb 14, 2026

/gemini review

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@guusdk guusdk force-pushed the OF-3180_OF-3179_Connection-closure-improvements branch from 8a0b927 to 84fd434 Compare February 14, 2026 21:16
@akrherz akrherz requested a review from Copilot February 14, 2026 21:33
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

…read pool

Add a dedicated thread pool executor to ConnectionManagerImpl for processing connection events asynchronously.

The notifyCloseListeners() method in AbstractConnection now dispatches listener invocations on this executor rather than invoking them on the calling thread. This prevents blocking or long-running listener implementations (e.g., those performing database or network I/O) from interfering with connection shutdown or I/O processing.

While all connection types benefit, this is particularly important for Netty-based connections where blocking the event loop thread can cause widespread connection stalls.

The new thread pool is configurable via system properties:
- `xmpp.connectionmanager.eventexecutor.threads` (default: 16)
- `xmpp.connectionmanager.eventexecutor.timeout` (default: 60s)
…ispatcher

The dispatcher for ConnectionCloseListener events was updated in a previous commit (for OF-3180) to ensure all listener invocations are executed asynchronously and offloaded from the calling thread. This change allows for significant simplification of the listener implementations, as they no longer need to manually wrap their logic in CompletableFuture.runAsync or thenRunAsync.

This commit removes redundant async wrapping in all ConnectionCloseListener implementations and uses the same executor for all async work.
Ensures consistency in listener execution. Critical cleanup runs before third-party listeners to prevent stale session state.

- Added `getPriority()` to `ConnectionCloseListener` (default: 0, built-in: 100)
- Updated `notifyCloseListeners()` to sort and execute listeners sequentially by priority
- Preserves insertion order for same-priority listeners
@guusdk guusdk force-pushed the OF-3180_OF-3179_Connection-closure-improvements branch from 84fd434 to f37cd69 Compare February 16, 2026 15:14
Copy link
Member

@Fishbowler Fishbowler left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This all seems logical. I love the priority impl, and love the clean-up of nested Futures.

The tests running gives some confidence that it's not utterly broken. But I think dogfooding makes sense to really prove it.

@akrherz akrherz merged commit 008321f into igniterealtime:main Feb 16, 2026
42 of 46 checks passed
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.

4 participants