Improve ConcurrentWebSocketSessionDecorator
Before this change the decorator ensured that for a specific WebSocket session only one thread at a time can send a message. Other threads attempting to send would have their messages buffered and each time that occurs, a check is also made to see if the buffer limit has been reached or the send time limit has been exceeded and if so the session is closed. This change adds further protection to ensure only one thread at a time can perform the session limit checks and attempt to close the session. Furthermore if the session has timed out and become unresponsive, attempts to close it may block yet another thread. Taking this into consideration this change also ensures that state associated with the session is cleaned first before an attempt is made to close the session. Issue: SPR-11450
This commit is contained in:
@@ -29,6 +29,7 @@ import java.util.concurrent.atomic.AtomicReference;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
/**
|
||||
* Unit tests for
|
||||
@@ -55,7 +56,7 @@ public class ConcurrentWebSocketSessionDecoratorTests {
|
||||
assertEquals(textMessage, session.getSentMessages().get(0));
|
||||
|
||||
assertEquals(0, concurrentSession.getBufferSize());
|
||||
assertEquals(0, concurrentSession.getInProgressSendTime());
|
||||
assertEquals(0, concurrentSession.getTimeSinceSendStarted());
|
||||
assertTrue(session.isOpen());
|
||||
}
|
||||
|
||||
@@ -86,14 +87,14 @@ public class ConcurrentWebSocketSessionDecoratorTests {
|
||||
|
||||
// ensure some send time elapses
|
||||
Thread.sleep(100);
|
||||
assertTrue(concurrentSession.getInProgressSendTime() > 0);
|
||||
assertTrue(concurrentSession.getTimeSinceSendStarted() > 0);
|
||||
|
||||
TextMessage payload = new TextMessage("payload");
|
||||
for (int i=0; i < 5; i++) {
|
||||
concurrentSession.sendMessage(payload);
|
||||
}
|
||||
|
||||
assertTrue(concurrentSession.getInProgressSendTime() > 0);
|
||||
assertTrue(concurrentSession.getTimeSinceSendStarted() > 0);
|
||||
assertEquals(5 * payload.getPayloadLength(), concurrentSession.getBufferSize());
|
||||
assertTrue(blockingSession.isOpen());
|
||||
}
|
||||
@@ -129,10 +130,13 @@ public class ConcurrentWebSocketSessionDecoratorTests {
|
||||
// ensure some send time elapses
|
||||
Thread.sleep(sendTimeLimit + 100);
|
||||
|
||||
TextMessage payload = new TextMessage("payload");
|
||||
concurrentSession.sendMessage(payload);
|
||||
|
||||
assertFalse(blockingSession.isOpen());
|
||||
try {
|
||||
TextMessage payload = new TextMessage("payload");
|
||||
concurrentSession.sendMessage(payload);
|
||||
fail("Expected exception");
|
||||
}
|
||||
catch (SessionLimitExceededException ex) {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -174,8 +178,12 @@ public class ConcurrentWebSocketSessionDecoratorTests {
|
||||
assertEquals(1023, concurrentSession.getBufferSize());
|
||||
assertTrue(blockingSession.isOpen());
|
||||
|
||||
concurrentSession.sendMessage(message);
|
||||
assertFalse(blockingSession.isOpen());
|
||||
try {
|
||||
concurrentSession.sendMessage(message);
|
||||
fail("Expected exception");
|
||||
}
|
||||
catch (SessionLimitExceededException ex) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -217,4 +225,47 @@ public class ConcurrentWebSocketSessionDecoratorTests {
|
||||
}
|
||||
}
|
||||
|
||||
// @Test
|
||||
// public void sendSessionLimitException() throws IOException, InterruptedException {
|
||||
//
|
||||
// BlockingSession blockingSession = new BlockingSession();
|
||||
// blockingSession.setOpen(true);
|
||||
// CountDownLatch sentMessageLatch = blockingSession.getSentMessageLatch();
|
||||
//
|
||||
// int sendTimeLimit = 10 * 1000;
|
||||
// int bufferSizeLimit = 1024;
|
||||
//
|
||||
// final ConcurrentWebSocketSessionDecorator concurrentSession =
|
||||
// new ConcurrentWebSocketSessionDecorator(blockingSession, sendTimeLimit, bufferSizeLimit);
|
||||
//
|
||||
// Executors.newSingleThreadExecutor().submit(new Runnable() {
|
||||
// @Override
|
||||
// public void run() {
|
||||
// TextMessage textMessage = new TextMessage("slow message");
|
||||
// try {
|
||||
// concurrentSession.sendMessage(textMessage);
|
||||
// }
|
||||
// catch (IOException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// assertTrue(sentMessageLatch.await(5, TimeUnit.SECONDS));
|
||||
//
|
||||
// StringBuilder sb = new StringBuilder();
|
||||
// for (int i=0 ; i < 1023; i++) {
|
||||
// sb.append("a");
|
||||
// }
|
||||
//
|
||||
// TextMessage message = new TextMessage(sb.toString());
|
||||
// concurrentSession.sendMessage(message);
|
||||
//
|
||||
// assertEquals(1023, concurrentSession.getBufferSize());
|
||||
// assertTrue(blockingSession.isOpen());
|
||||
//
|
||||
// concurrentSession.sendMessage(message);
|
||||
// assertFalse(blockingSession.isOpen());
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user