@Test public void testMessageGroupWithAddedMessage() throws Exception { GemfireMessageStore store = new GemfireMessageStore(this.cache); store.afterPropertiesSet(); MessageGroup messageGroup = store.getMessageGroup(1); Message<?> message = new GenericMessage<String>("Hello"); messageGroup = store.addMessageToGroup(1, message); assertEquals(1, messageGroup.size()); // make sure the store is properly rebuild from Gemfire store = new GemfireMessageStore(this.cache); store.afterPropertiesSet(); messageGroup = store.getMessageGroup(1); assertEquals(1, messageGroup.size()); }
@Test @MongoDbAvailable public void testRemoveMessageFromTheGroup() throws Exception { MongoDbFactory mongoDbFactory = this.prepareMongoFactory(); MongoDbMessageStore store = new MongoDbMessageStore(mongoDbFactory); MessageGroup messageGroup = store.getMessageGroup(1); Message<?> message = new GenericMessage<String>("2"); store.addMessageToGroup(1, new GenericMessage<String>("1")); store.addMessageToGroup(1, message); messageGroup = store.addMessageToGroup(1, new GenericMessage<String>("3")); assertEquals(3, messageGroup.size()); messageGroup = store.removeMessageFromGroup(1, message); assertEquals(2, messageGroup.size()); }
@Test public void testNonExistingEmptyMessageGroup() throws Exception { GemfireMessageStore store = new GemfireMessageStore(this.cache); store.afterPropertiesSet(); MessageGroup messageGroup = store.getMessageGroup(1); assertNotNull(messageGroup); assertTrue(messageGroup instanceof SimpleMessageGroup); assertEquals(0, messageGroup.size()); }
@Test @MongoDbAvailable public void testRemoveMessageGroup() throws Exception { MongoDbFactory mongoDbFactory = this.prepareMongoFactory(); MongoDbMessageStore store = new MongoDbMessageStore(mongoDbFactory); MessageGroup messageGroup = store.getMessageGroup(1); Message<?> message = new GenericMessage<String>("Hello"); UUID id = message.getHeaders().getId(); messageGroup = store.addMessageToGroup(1, message); assertEquals(1, messageGroup.size()); message = store.getMessage(id); assertNotNull(message); store.removeMessageGroup(1); MessageGroup messageGroupA = store.getMessageGroup(1); assertEquals(0, messageGroupA.size()); assertFalse(messageGroupA.equals(messageGroup)); }
@Test @MongoDbAvailable public void testNonExistingEmptyMessageGroup() throws Exception { MongoDbFactory mongoDbFactory = this.prepareMongoFactory(); MongoDbMessageStore store = new MongoDbMessageStore(mongoDbFactory); MessageGroup messageGroup = store.getMessageGroup(1); assertNotNull(messageGroup); assertTrue(messageGroup instanceof SimpleMessageGroup); assertEquals(0, messageGroup.size()); }
@Test public void testRemoveMessageFromTheGroup() throws Exception { GemfireMessageStore store = new GemfireMessageStore(this.cache); store.afterPropertiesSet(); MessageGroup messageGroup = store.getMessageGroup(1); Message<?> message = new GenericMessage<String>("2"); messageGroup = store.addMessageToGroup(messageGroup.getGroupId(), new GenericMessage<String>("1")); messageGroup = store.getMessageGroup(1); assertEquals(1, messageGroup.size()); Thread.sleep( 1); // since it adds to a local region some times CREATED_DATE ends up to be the same // Unrealistic in a real scenario messageGroup = store.addMessageToGroup(messageGroup.getGroupId(), message); messageGroup = store.getMessageGroup(1); assertEquals(2, messageGroup.size()); Thread.sleep(1); messageGroup = store.addMessageToGroup(messageGroup.getGroupId(), new GenericMessage<String>("3")); messageGroup = store.getMessageGroup(1); assertEquals(3, messageGroup.size()); messageGroup = store.removeMessageFromGroup(messageGroup.getGroupId(), message); messageGroup = store.getMessageGroup(1); assertEquals(2, messageGroup.size()); // make sure the store is properly rebuild from Gemfire store = new GemfireMessageStore(this.cache); store.afterPropertiesSet(); messageGroup = store.getMessageGroup(1); assertEquals(2, messageGroup.size()); }
@Test public void testRemoveMessageGroup() throws Exception { GemfireMessageStore store = new GemfireMessageStore(this.cache); store.afterPropertiesSet(); MessageGroup messageGroup = store.getMessageGroup(1); Message<?> message = new GenericMessage<String>("Hello"); messageGroup = store.addMessageToGroup(messageGroup.getGroupId(), message); assertEquals(1, messageGroup.size()); store.removeMessageGroup(1); MessageGroup messageGroupA = store.getMessageGroup(1); assertNotSame(messageGroup, messageGroupA); assertEquals(0, messageGroupA.getMessages().size()); assertEquals(0, messageGroupA.size()); // make sure the store is properly rebuild from Gemfire store = new GemfireMessageStore(this.cache); store.afterPropertiesSet(); messageGroup = store.getMessageGroup(1); assertEquals(0, messageGroup.getMessages().size()); assertEquals(0, messageGroup.size()); }
@Test @MongoDbAvailable public void testMessageGroupWithAddedMessage() throws Exception { MongoDbFactory mongoDbFactory = this.prepareMongoFactory(); MongoDbMessageStore store = new MongoDbMessageStore(mongoDbFactory); MessageGroup messageGroup = store.getMessageGroup(1); Message<?> messageA = new GenericMessage<String>("A"); Message<?> messageB = new GenericMessage<String>("B"); store.addMessageToGroup(1, messageA); messageGroup = store.addMessageToGroup(1, messageB); assertEquals(2, messageGroup.size()); Message<?> retrievedMessage = store.getMessage(messageA.getHeaders().getId()); assertNotNull(retrievedMessage); assertEquals(retrievedMessage.getHeaders().getId(), messageA.getHeaders().getId()); // ensure that 'message_group' header that is only used internally is not propagated assertNull(retrievedMessage.getHeaders().get("message_group")); }
protected void expireGroup(Object correlationKey, MessageGroup group) { if (logger.isInfoEnabled()) { logger.info("Expiring MessageGroup with correlationKey[" + correlationKey + "]"); } if (sendPartialResultOnExpiry) { if (logger.isDebugEnabled()) { logger.debug( "Prematurely releasing partially complete group with key [" + correlationKey + "] to: " + getOutputChannel()); } completeGroup(correlationKey, group); } else { if (logger.isDebugEnabled()) { logger.debug( "Discarding messages of partially complete group with key [" + correlationKey + "] to: " + (this.discardChannelName != null ? this.discardChannelName : this.discardChannel)); } for (Message<?> message : group.getMessages()) { discardMessage(message); } } if (this.applicationEventPublisher != null) { this.applicationEventPublisher.publishEvent( new MessageGroupExpiredEvent( this, correlationKey, group.size(), new Date(group.getLastModified()), new Date(), !sendPartialResultOnExpiry)); } }
protected void forceComplete(MessageGroup group) { Object correlationKey = group.getGroupId(); // UUIDConverter is no-op if already converted Lock lock = this.lockRegistry.obtain(UUIDConverter.getUUID(correlationKey).toString()); boolean removeGroup = true; try { lock.lockInterruptibly(); try { ScheduledFuture<?> scheduledFuture = this.expireGroupScheduledFutures.remove(UUIDConverter.getUUID(correlationKey)); if (scheduledFuture != null) { boolean canceled = scheduledFuture.cancel(false); if (canceled && logger.isDebugEnabled()) { logger.debug("Cancel 'forceComplete' scheduling for MessageGroup [ " + group + "]."); } } MessageGroup groupNow = group; /* * If the group argument is not already complete, * re-fetch it because it might have changed while we were waiting on * its lock. If the last modified timestamp changed, defer the completion * because the selection condition may have changed such that the group * would no longer be eligible. If the timestamp changed, it's a completely new * group and should not be reaped on this cycle. * * If the group argument is already complete, do not re-fetch. * Note: not all message stores provide a direct reference to its internal * group so the initial 'isComplete()` will only return true for those stores if * the group was already complete at the time of its selection as a candidate. * * If the group is marked complete, only consider it * for reaping if it's empty (and both timestamps are unaltered). */ 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()) { if (groupSize > 0) { if (releaseStrategy.canRelease(groupNow)) { completeGroup(correlationKey, groupNow); } else { expireGroup(correlationKey, groupNow); } if (!this.expireGroupsUponTimeout) { afterRelease(groupNow, groupNow.getMessages(), true); removeGroup = false; } } else { /* * By default empty groups are removed on the same schedule as non-empty * groups. A longer timeout for empty groups can be enabled by * setting minimumTimeoutForEmptyGroups. */ removeGroup = lastModifiedNow <= (System.currentTimeMillis() - this.minimumTimeoutForEmptyGroups); if (removeGroup && logger.isDebugEnabled()) { logger.debug("Removing empty group: " + correlationKey); } } } else { removeGroup = false; if (logger.isDebugEnabled()) { logger.debug( "Group expiry candidate (" + correlationKey + ") has changed - it may be reconsidered for a future expiration"); } } } catch (MessageDeliveryException e) { removeGroup = false; if (logger.isDebugEnabled()) { logger.debug( "Group expiry candidate (" + correlationKey + ") has been affected by MessageDeliveryException - " + "it may be reconsidered for a future expiration one more time"); } throw e; } finally { try { if (removeGroup) { this.remove(group); } } finally { lock.unlock(); } } } catch (InterruptedException ie) { Thread.currentThread().interrupt(); logger.debug("Thread was interrupted while trying to obtain lock"); } }