@Override protected void handleMessageInternal(Message<?> message) throws Exception { Object correlationKey = correlationStrategy.getCorrelationKey(message); Assert.state( correlationKey != null, "Null correlation not allowed. Maybe the CorrelationStrategy is failing?"); if (logger.isDebugEnabled()) { logger.debug("Handling message with correlationKey [" + correlationKey + "]: " + message); } UUID groupIdUuid = UUIDConverter.getUUID(correlationKey); Lock lock = this.lockRegistry.obtain(groupIdUuid.toString()); lock.lockInterruptibly(); try { ScheduledFuture<?> scheduledFuture = this.expireGroupScheduledFutures.remove(groupIdUuid); if (scheduledFuture != null) { boolean canceled = scheduledFuture.cancel(true); if (canceled && logger.isDebugEnabled()) { logger.debug( "Cancel 'forceComplete' scheduling for MessageGroup with Correlation Key [ " + correlationKey + "]."); } } MessageGroup messageGroup = messageStore.getMessageGroup(correlationKey); if (this.sequenceAware) { messageGroup = new SequenceAwareMessageGroup(messageGroup); } if (!messageGroup.isComplete() && messageGroup.canAdd(message)) { if (logger.isTraceEnabled()) { logger.trace("Adding message to group [ " + messageGroup + "]"); } messageGroup = this.store(correlationKey, message); if (releaseStrategy.canRelease(messageGroup)) { Collection<Message<?>> completedMessages = null; try { completedMessages = this.completeGroup(message, correlationKey, messageGroup); } finally { // Always clean up even if there was an exception // processing messages this.afterRelease(messageGroup, completedMessages); } } else { scheduleGroupToForceComplete(messageGroup); } } else { discardMessage(message); } } finally { lock.unlock(); } }
public final void setMessageStore(MessageGroupStore store) { this.messageStore = store; store.registerMessageGroupExpiryCallback( new MessageGroupCallback() { @Override public void execute(MessageGroupStore messageGroupStore, MessageGroup group) { forceReleaseProcessor.processMessageGroup(group); } }); }
protected MessageGroup store(Object correlationKey, Message<?> message) { return messageStore.addMessageToGroup(correlationKey, message); }
void remove(MessageGroup group) { Object correlationKey = group.getGroupId(); messageStore.removeMessageGroup(correlationKey); }
@Test @RedisAvailable public void testDelayerHandlerRescheduleWithRedisMessageStore() throws Exception { AbstractApplicationContext context = new ClassPathXmlApplicationContext( "DelayerHandlerRescheduleIntegrationTests-context.xml", this.getClass()); MessageChannel input = context.getBean("input", MessageChannel.class); MessageGroupStore messageStore = context.getBean("messageStore", MessageGroupStore.class); String delayerMessageGroupId = DELAYER_ID + ".messageGroupId"; messageStore.removeMessageGroup(delayerMessageGroupId); Message<String> message1 = MessageBuilder.withPayload("test1").build(); input.send(message1); input.send(MessageBuilder.withPayload("test2").build()); // Emulate restart and check DB state before next start // Interrupt taskScheduler as quickly as possible ThreadPoolTaskScheduler taskScheduler = (ThreadPoolTaskScheduler) IntegrationContextUtils.getTaskScheduler(context); taskScheduler.shutdown(); taskScheduler.getScheduledExecutor().awaitTermination(10, TimeUnit.SECONDS); context.destroy(); try { context.getBean("input", MessageChannel.class); fail("IllegalStateException expected"); } catch (Exception e) { assertTrue(e instanceof IllegalStateException); assertTrue( e.getMessage() .contains("BeanFactory not initialized or already closed - call 'refresh'")); } assertEquals(1, messageStore.getMessageGroupCount()); assertEquals(delayerMessageGroupId, messageStore.iterator().next().getGroupId()); assertEquals(2, messageStore.messageGroupSize(delayerMessageGroupId)); assertEquals(2, messageStore.getMessageCountForAllMessageGroups()); MessageGroup messageGroup = messageStore.getMessageGroup(delayerMessageGroupId); Message<?> messageInStore = messageGroup.getMessages().iterator().next(); Object payload = messageInStore.getPayload(); // INT-3049 assertTrue(payload instanceof DelayHandler.DelayedMessageWrapper); assertEquals(message1, ((DelayHandler.DelayedMessageWrapper) payload).getOriginal()); context.refresh(); PollableChannel output = context.getBean("output", PollableChannel.class); Message<?> message = output.receive(20000); assertNotNull(message); Object payload1 = message.getPayload(); message = output.receive(20000); assertNotNull(message); Object payload2 = message.getPayload(); assertNotSame(payload1, payload2); assertEquals(1, messageStore.getMessageGroupCount()); assertEquals(0, messageStore.messageGroupSize(delayerMessageGroupId)); messageStore.removeMessageGroup(delayerMessageGroupId); }