@@ -37,7 +37,7 @@ public class WebSocketScopeManager {
3737 // used to ping WS connections
3838 private static final byte [] PING_BYTES = "PING!" .getBytes ();
3939
40- // one executor per scope manager
40+ // one executor per scope manager (2 slots - one for pinger, one for notifications)
4141 private ExecutorService executor = Executors .newFixedThreadPool (2 );
4242
4343 // future for the ws pinger
@@ -150,50 +150,55 @@ public boolean addWebSocketScope(WebSocketScope webSocketScope) {
150150 if (scopes .putIfAbsent (path , webSocketScope ) == null ) {
151151 log .info ("addWebSocketScope: {}" , webSocketScope );
152152 notifyListeners (WebSocketEvent .SCOPE_ADDED , webSocketScope , null );
153- // ensure the ping future exists, if not spawn it
154- if (pingFuture == null || pingFuture .isDone ()) {
155- final String appScopeName = appScope != null ? appScope .getName () : "default" ;
156- pingFuture = executor .submit (() -> {
157- final String oldName = Thread .currentThread ().getName ();
158- Thread .currentThread ().setName (String .format ("WebSocketPinger@%s" , appScopeName ));
159- do {
160- scopes .forEach ((sName , wsScope ) -> {
161- log .trace ("start pinging scope: {}" , sName );
162- wsScope .getConns ().forEach (wsConn -> {
163- try {
164- // ping connected websocket
165- if (wsConn .isConnected ()) {
166- log .trace ("pinging ws: {} on scope: {}" , wsConn .getWsSessionId (), sName );
167- try {
168- wsConn .sendPing (PING_BYTES );
169- } catch (Exception e ) {
170- log .debug ("Exception pinging connection: {} connection will be closed" , wsConn .getSessionId (), e );
153+ if (websocketPingInterval < 0 ) {
154+ log .debug ("Websocket pinger is disabled" );
155+ } else {
156+ // ensure the ping future exists, if not spawn it
157+ if (pingFuture == null || pingFuture .isDone ()) {
158+ log .debug ("Websocket ping interval: {}" , websocketPingInterval );
159+ final String appScopeName = appScope != null ? appScope .getName () : "default" ;
160+ pingFuture = executor .submit (() -> {
161+ final String oldName = Thread .currentThread ().getName ();
162+ Thread .currentThread ().setName (String .format ("WebSocketPinger@%s" , appScopeName ));
163+ do {
164+ scopes .forEach ((sName , wsScope ) -> {
165+ log .trace ("start pinging scope: {}" , sName );
166+ wsScope .getConns ().forEach (wsConn -> {
167+ try {
168+ // ping connected websocket
169+ if (wsConn .isConnected ()) {
170+ log .trace ("pinging ws: {} on scope: {}" , wsConn .getWsSessionId (), sName );
171+ try {
172+ wsConn .sendPing (PING_BYTES );
173+ } catch (Exception e ) {
174+ log .debug ("Exception pinging connection: {} connection will be closed" , wsConn .getSessionId (), e );
175+ // if the connection isn't connected, remove them
176+ wsScope .removeConnection (wsConn );
177+ // if the ping fails, consider them gone
178+ wsConn .close ();
179+ }
180+ } else {
181+ log .debug ("Removing unconnected connection: {} during ping loop" , wsConn .getSessionId ());
171182 // if the connection isn't connected, remove them
172183 wsScope .removeConnection (wsConn );
173- // if the ping fails, consider them gone
174- wsConn .close ();
175184 }
176- } else {
177- log .debug ("Removing unconnected connection: {} during ping loop" , wsConn .getSessionId ());
178- // if the connection isn't connected, remove them
179- wsScope .removeConnection (wsConn );
185+ } catch (Exception e ) {
186+ log .warn ("Exception in WS pinger" , e );
180187 }
181- } catch (Exception e ) {
182- log .warn ("Exception in WS pinger" , e );
183- }
188+ });
189+ log .trace ("finished pinging scope: {}" , sName );
184190 });
185- log .trace ("finished pinging scope: {}" , sName );
186- });
187- // sleep for interval
188- try {
189- Thread .sleep (websocketPingInterval );
190- } catch (InterruptedException e ) {
191- }
192- } while (!scopes .isEmpty ());
193- // reset ping future
194- pingFuture = null ;
195- Thread .currentThread ().setName (oldName );
196- });
191+ // sleep for interval
192+ try {
193+ Thread .sleep (websocketPingInterval );
194+ } catch (InterruptedException e ) {
195+ }
196+ } while (!scopes .isEmpty ());
197+ // reset ping future
198+ pingFuture = null ;
199+ Thread .currentThread ().setName (oldName );
200+ });
201+ }
197202 }
198203 return true ;
199204 }
@@ -443,6 +448,9 @@ public void setCopyListeners(boolean copy) {
443448 }
444449
445450 public static void setWebsocketPingInterval (long websocketPingInterval ) {
451+ if (websocketPingInterval < 0 ) {
452+ log .warn ("Setting the ping interval to a negative value will disable the internal ping worker" );
453+ }
446454 WebSocketScopeManager .websocketPingInterval = websocketPingInterval ;
447455 }
448456
0 commit comments