@Override public boolean canRelease(MessageGroup messageGroup) { boolean canRelease = false; int size = messageGroup.size(); if (this.releasePartialSequences && size > 0) { if (logger.isTraceEnabled()) { logger.trace("Considering partial release of group [" + messageGroup + "]"); } Collection<Message<?>> messages = messageGroup.getMessages(); Message<?> minMessage = Collections.min(messages, this.comparator); int nextSequenceNumber = new IntegrationMessageHeaderAccessor(minMessage).getSequenceNumber(); int lastReleasedMessageSequence = messageGroup.getLastReleasedMessageSequenceNumber(); if (nextSequenceNumber - lastReleasedMessageSequence == 1) { canRelease = true; } } else { if (size == 0) { canRelease = true; } else { int sequenceSize = messageGroup.getSequenceSize(); // If there is no sequence then it must be incomplete.... if (sequenceSize == size) { canRelease = true; } } } return canRelease; }
@Override protected MessageGroup copy(MessageGroup group) { Object groupId = group.getGroupId(); Lock lock = this.lockRegistry.obtain(groupId); try { lock.lockInterruptibly(); try { MessageGroup simpleMessageGroup = getMessageGroupFactory() .create(group.getMessages(), groupId, group.getTimestamp(), group.isComplete()); simpleMessageGroup.setLastModified(group.getLastModified()); simpleMessageGroup.setLastReleasedMessageSequenceNumber(group.getLastReleasedMessageSequenceNumber()); return simpleMessageGroup; } finally { lock.unlock(); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new MessagingException("Interrupted while obtaining lock", e); } }
public SimpleMessageGroup(MessageGroup messageGroup) { this(messageGroup.getMessages(), messageGroup.getGroupId(), messageGroup.getTimestamp(), messageGroup.isComplete()); }
public MessageGroupMetadata(MessageGroup messageGroup) { Assert.notNull(messageGroup, "'messageGroup' must not be null"); for (Message<?> message : messageGroup.getMessages()) { this.messageIds.add(message.getHeaders().getId()); } this.complete = messageGroup.isComplete(); this.timestamp = messageGroup.getTimestamp(); this.lastReleasedMessageSequenceNumber = messageGroup.getLastReleasedMessageSequenceNumber(); this.lastModified = messageGroup.getLastModified(); }
@Override public boolean canRelease(MessageGroup messages) { long elapsedTime = System.currentTimeMillis() - findEarliestTimestamp(messages); return messages.isComplete() || messages.getMessages().size() >= this.threshold || elapsedTime > this.timeout; }
protected void forceComplete(MessageGroup group) { Object correlationKey = group.getGroupId(); if (!group.isComplete()) { groupNow = this.messageStore.getMessageGroup(correlationKey); long lastModifiedNow = groupNow.getLastModified(); int groupSize = groupNow.size(); if ((!groupNow.isComplete() || groupSize == 0) && group.getLastModified() == lastModifiedNow && group.getTimestamp() == groupNow.getTimestamp()) { afterRelease(groupNow, groupNow.getMessages(), true); removeGroup = false;
@Override public void setLastReleasedSequenceNumberForGroup(Object groupId, int sequenceNumber) { Lock lock = this.lockRegistry.obtain(groupId); try { lock.lockInterruptibly(); try { MessageGroup group = this.groupIdToMessageGroup.get(groupId); Assert.notNull(group, "MessageGroup for groupId '" + groupId + "' " + "can not be located while attempting to set 'lastReleasedSequenceNumber'"); group.setLastReleasedMessageSequenceNumber(sequenceNumber); group.setLastModified(System.currentTimeMillis()); } finally { lock.unlock(); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new MessagingException("Interrupted while obtaining lock", e); } }
/** * Release the group if it has more messages than the threshold and has not previously been released. * It is possible that more messages than the threshold could be released, but only if multiple consumers * receive messages from the same group concurrently. */ @Override public boolean canRelease(MessageGroup group) { return group.size() >= this.threshold; }
@Override public Object processMessageGroup(MessageGroup group) { return group.getMessages(); }
@Test @RedisAvailable public void testMessageGroupUpdatedDateChangesWithEachAddedMessage() throws Exception { RedisConnectionFactory jcf = getConnectionFactoryForTest(); RedisMessageStore store = new RedisMessageStore(jcf); Message<?> message = new GenericMessage<>("Hello"); MessageGroup messageGroup = store.addMessageToGroup(this.groupId, message); assertEquals(1, messageGroup.size()); long createdTimestamp = messageGroup.getTimestamp(); long updatedTimestamp = messageGroup.getLastModified(); assertEquals(createdTimestamp, updatedTimestamp); Thread.sleep(10); message = new GenericMessage<>("Hello"); messageGroup = store.addMessageToGroup(this.groupId, message); createdTimestamp = messageGroup.getTimestamp(); updatedTimestamp = messageGroup.getLastModified(); assertTrue(updatedTimestamp > createdTimestamp); // make sure the store is properly rebuild from Redis store = new RedisMessageStore(jcf); messageGroup = store.getMessageGroup(this.groupId); assertEquals(2, messageGroup.size()); }
protected void expireGroup(Object correlationKey, MessageGroup group, Lock lock) { if (this.logger.isInfoEnabled()) { this.logger.info("Expiring MessageGroup with correlationKey[" + correlationKey + "]"); } if (this.sendPartialResultOnExpiry) { if (this.logger.isDebugEnabled()) { this.logger.debug("Prematurely releasing partially complete group with key [" + correlationKey + "] to: " + getOutputChannel()); } completeGroup(correlationKey, group, lock); } else { if (this.logger.isDebugEnabled()) { this.logger.debug("Discarding messages of partially complete group with key [" + correlationKey + "] to: " + (this.discardChannelName != null ? this.discardChannelName : this.discardChannel)); } if (this.releaseLockBeforeSend) { lock.unlock(); } group.getMessages() .forEach(this::discardMessage); } if (this.applicationEventPublisher != null) { this.applicationEventPublisher.publishEvent( new MessageGroupExpiredEvent(this, correlationKey, group.size(), new Date(group.getLastModified()), new Date(), !this.sendPartialResultOnExpiry)); } }
private void removeEmptyGroupAfterTimeout(MessageGroup messageGroup, long timeout) { Object groupId = messageGroup.getGroupId(); UUID groupUuid = UUIDConverter.getUUID(groupId); ScheduledFuture<?> scheduledFuture = getTaskScheduler() boolean removeGroup = groupNow.size() == 0 && groupNow.getLastModified() <= (System.currentTimeMillis() - this.minimumTimeoutForEmptyGroups); if (removeGroup) {
@Test public void testCompleteMessageGroup() throws Exception { GemfireMessageStore store = new GemfireMessageStore(region); MessageGroup messageGroup = store.getMessageGroup(1); Message<?> messageToMark = new GenericMessage<String>("1"); store.addMessagesToGroup(messageGroup.getGroupId(), messageToMark); store.completeGroup(messageGroup.getGroupId()); messageGroup = store.getMessageGroup(1); assertTrue(messageGroup.isComplete()); }
@Test @Transactional public void testCompleteMessageGroup() throws Exception { String groupId = "X"; Message<String> message = MessageBuilder.withPayload("foo").setCorrelationId(groupId).build(); messageStore.addMessageToGroup(groupId, message); messageStore.completeGroup(groupId); MessageGroup group = messageStore.getMessageGroup(groupId); assertTrue(group.isComplete()); assertEquals(1, group.size()); }
messageStore.completeGroup(messageGroup.getGroupId()); for (Message<?> message : messageGroup.getMessages()) { messageStore.removeMessagesFromGroup(groupId, message); assertTrue(messageGroup.isComplete());
@Test @Transactional public void testAddAndGetMessageGroup() throws Exception { String groupId = "X"; Message<String> message = MessageBuilder.withPayload("foo").setCorrelationId(groupId).build(); long now = System.currentTimeMillis(); messageStore.addMessageToGroup(groupId, message); MessageGroup group = messageStore.getMessageGroup(groupId); assertEquals(1, group.size()); assertTrue("Timestamp too early: " + group.getTimestamp() + "<" + now, group.getTimestamp() >= now); }
@Test public void testLastReleasedSequenceNumber() throws Exception { GemfireMessageStore store = new GemfireMessageStore(region); MessageGroup messageGroup = store.getMessageGroup(1); Message<?> messageToMark = new GenericMessage<String>("1"); store.addMessagesToGroup(messageGroup.getGroupId(), messageToMark); store.setLastReleasedSequenceNumberForGroup(messageGroup.getGroupId(), 5); messageGroup = store.getMessageGroup(1); assertEquals(5, messageGroup.getLastReleasedMessageSequenceNumber()); }
@Override public Object getGroupId() { return this.original.getGroupId(); }
@Test public void shouldExpireMessageGroup() throws Exception { TestMessageStore store = new TestMessageStore(); final List<String> list = new ArrayList<String>(); store.registerMessageGroupExpiryCallback((messageGroupStore, group) -> { list.add(group.getOne().getPayload().toString()); messageGroupStore.removeMessageGroup(group.getGroupId()); }); store.expireMessageGroups(-10000); assertEquals("[foo]", list.toString()); assertEquals(0, store.getMessageGroup("bar").size()); }
final Object groupId = messageGroup.getGroupId(); final long timestamp = messageGroup.getTimestamp(); final long lastModified = messageGroup.getLastModified(); ScheduledFuture<?> scheduledFuture = getTaskScheduler() .schedule(() -> {