@Override public Message<Object> receive() { for (Object key : this.correlationLocks.keySet()) { Object lock = getLock(key); synchronized (lock) { MessageGroup group = this.store.getMessageGroup(key); //group might be removed by another thread if (group != null) { if (this.releaseStrategy.canRelease(group)) { Message<?> nextMessage = null; Iterator<Message<?>> messages = group.getMessages().iterator(); if (messages.hasNext()) { nextMessage = messages.next(); this.store.removeMessagesFromGroup(key, nextMessage); if (log.isDebugEnabled()) { log.debug(String.format("Released message for key [%s]: %s.", key, nextMessage)); } } else { remove(key); } @SuppressWarnings("unchecked") Message<Object> result = (Message<Object>) nextMessage; return result; } } } } return null; }
@Before public void initializeBarrier() { barrier = new CorrelatingMessageBarrier(); barrier.setCorrelationStrategy(correlationStrategy); barrier.setReleaseStrategy(releaseStrategy); when(correlationStrategy.getCorrelationKey(isA(Message.class))).thenReturn("foo"); when(releaseStrategy.canRelease(isA(MessageGroup.class))).thenReturn(true); }
@Test public void shouldRemoveKeyWithoutLockingOnEmptyQueue() throws InterruptedException { Message<Object> message = testMessage(); Message<Object> message2 = testMessage(); barrier.handleMessage(message); verify(correlationStrategy).getCorrelationKey(message); assertThat(barrier.receive(), is(notNullValue())); barrier.handleMessage(message2); assertThat(barrier.receive(), is(notNullValue())); assertThat(barrier.receive(), is(nullValue())); }
@Override protected void handleMessageInternal(Message<?> message) throws Exception { Object correlationKey = this.correlationStrategy.getCorrelationKey(message); Object lock = getLock(correlationKey); synchronized (lock) { this.store.addMessagesToGroup(correlationKey, message); } if (log.isDebugEnabled()) { log.debug(String.format("Handled message for key [%s]: %s.", correlationKey, message)); } }
@Test(timeout = 10000) public void shouldNotDropMessageOrBlockSendingThread() { OneMessagePerKeyReleaseStrategy trackingReleaseStrategy = new OneMessagePerKeyReleaseStrategy(); barrier.setReleaseStrategy(trackingReleaseStrategy); final CountDownLatch start = new CountDownLatch(1); final CountDownLatch sent = new CountDownLatch(200); ExecutorService exec = Executors.newSingleThreadExecutor(); for (int i = 0; i < 200; i++) { sendAsynchronously(barrier, testMessage(), start, sent, exec); } start.countDown(); try { sent.await(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } assertThat((barrier.receive()), is(notNullValue())); for (int i = 0; i < 199; i++) { trackingReleaseStrategy.release("foo"); assertThat((barrier.receive()), is(notNullValue())); } exec.shutdownNow(); }
@Override protected void handleMessageInternal(Message<?> message) throws Exception { Object correlationKey = this.correlationStrategy.getCorrelationKey(message); Object lock = getLock(correlationKey); synchronized (lock) { this.store.addMessagesToGroup(correlationKey, message); } if (log.isDebugEnabled()) { log.debug(String.format("Handled message for key [%s]: %s.", correlationKey, message)); } }
@Override public Message<Object> receive() { for (Object key : this.correlationLocks.keySet()) { Object lock = getLock(key); synchronized (lock) { MessageGroup group = this.store.getMessageGroup(key); //group might be removed by another thread if (group != null) { if (this.releaseStrategy.canRelease(group)) { Message<?> nextMessage = null; Iterator<Message<?>> messages = group.getMessages().iterator(); if (messages.hasNext()) { nextMessage = messages.next(); this.store.removeMessagesFromGroup(key, nextMessage); if (log.isDebugEnabled()) { log.debug(String.format("Released message for key [%s]: %s.", key, nextMessage)); } } else { remove(key); } @SuppressWarnings("unchecked") Message<Object> result = (Message<Object>) nextMessage; return result; } } } } return null; }
@Test public void shouldPassMessage() { Message<Object> message = testMessage(); barrier.handleMessage(message); assertThat(barrier.receive(), is(message)); }