INT-1561: add counters to message stores

This commit is contained in:
Dave Syer
2010-11-09 12:29:35 +00:00
parent 35aeaff97b
commit 941b1127d1
9 changed files with 268 additions and 28 deletions

View File

@@ -19,6 +19,7 @@ import java.util.LinkedHashSet;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.jmx.export.annotation.ManagedAttribute;
/**
* @author Dave Syer
@@ -69,6 +70,33 @@ public abstract class AbstractMessageGroupStore implements MessageGroupStore, It
public abstract Iterator<MessageGroup> iterator();
@ManagedAttribute
public int getMessageCountForAllMessageGroups() {
int count = 0;
for (MessageGroup group : this) {
count += group.size();
}
return count;
}
@ManagedAttribute
public int getMarkedMessageCountForAllMessageGroups() {
int count = 0;
for (MessageGroup group : this) {
count += group.getMarked().size();
}
return count;
}
@ManagedAttribute
public int getMessageGroupCount() {
int count = 0;
for (@SuppressWarnings("unused") MessageGroup group : this) {
count ++;
}
return count;
}
private void expire(MessageGroup group) {
RuntimeException exception = null;

View File

@@ -13,6 +13,7 @@
package org.springframework.integration.store;
import org.springframework.integration.Message;
import org.springframework.jmx.export.annotation.ManagedAttribute;
/**
* Interface for storage operations on groups of messages linked by a group id.
@@ -24,6 +25,36 @@ import org.springframework.integration.Message;
*/
public interface MessageGroupStore {
/**
* Optional attribute giving the number of messages in the store over all groups. Implementations may decline to
* respond by throwing an exception.
*
* @return the number of messages
* @throws UnsupportedOperationException if not implemented
*/
@ManagedAttribute
int getMessageCountForAllMessageGroups();
/**
* Optional attribute giving the number of marked messages in the store for all groups. Implementations may decline
* to respond by throwing an exception.
*
* @return the number of marked messages in each group
* @throws UnsupportedOperationException if not implemented
*/
@ManagedAttribute
int getMarkedMessageCountForAllMessageGroups();
/**
* Optional attribute giving the number of message groups. Implementations may decline
* to respond by throwing an exception.
*
* @return the number message groups
* @throws UnsupportedOperationException if not implemented
*/
@ManagedAttribute
int getMessageGroupCount();
/**
* Return all Messages currently in the MessageStore that were stored using
* {@link #addMessageToGroup(Object, Message)} with this group id.
@@ -43,14 +74,14 @@ public interface MessageGroupStore {
/**
* Persist the mark on all the messages from the group. The group is modified in the process as all its unmarked
* messages become marked.
*
*
* @param group a MessageGroup with no unmarked messages
*/
MessageGroup markMessageGroup(MessageGroup group);
/**
* Persist a deletion on a single message from the group. The group is modified to reflect that 'messageToRemove' is no
* longer present in the group.
* Persist a deletion on a single message from the group. The group is modified to reflect that 'messageToRemove' is
* no longer present in the group.
* @param key the groupId for the group containing the message
* @param messageToRemove the message to be removed
*/
@@ -66,14 +97,14 @@ public interface MessageGroupStore {
/**
* Remove the message group with this id.
*
*
* @param groupId the id of the group to remove
*/
void removeMessageGroup(Object groupId);
/**
* Register a callback for when a message group is expired through {@link #expireMessageGroups(long)}.
*
*
* @param callback a callback to execute when a message group is cleaned up
*/
void registerMessageGroupExpiryCallback(MessageGroupCallback callback);
@@ -83,10 +114,10 @@ public interface MessageGroupStore {
* each of the registered callbacks on them in turn. For example: call with a timeout of 100 to expire all groups
* that were created more than 100 milliseconds ago, and are not yet complete. Use a timeout of 0 (or negative to be
* on the safe side) to expire all message groups.
*
*
* @param timeout the timeout threshold to use
* @return the number of message groups expired
*
*
* @see #registerMessageGroupExpiryCallback(MessageGroupCallback)
*/
int expireMessageGroups(long timeout);

View File

@@ -19,6 +19,7 @@ package org.springframework.integration.store;
import java.util.UUID;
import org.springframework.integration.Message;
import org.springframework.jmx.export.annotation.ManagedAttribute;
/**
* Strategy interface for storing and retrieving messages.
@@ -39,8 +40,8 @@ public interface MessageStore {
/**
* Put the provided Message into the MessageStore. The store may need to mutate the message internally, and if it
* does then the return value can be different than the input. The id of the return value will be used as an index
* so that the {@link #getMessage(UUID)} and {@link #removeMessage(UUID)} behave properly. Since messages are immutable, putting
* the same message more than once is a no-op.
* so that the {@link #getMessage(UUID)} and {@link #removeMessage(UUID)} behave properly. Since messages are
* immutable, putting the same message more than once is a no-op.
*
* @return the message that was stored
*/
@@ -52,4 +53,14 @@ public interface MessageStore {
*/
Message<?> removeMessage(UUID id);
/**
* Optional attribute giving the number of messages in the store. Implementations may decline to respond by throwing
* an exception.
*
* @return the number of messages
* @throws UnsupportedOperationException if not implemented
*/
@ManagedAttribute
int getMessageCount();
}

View File

@@ -13,17 +13,19 @@
package org.springframework.integration.store;
import org.springframework.integration.Message;
import org.springframework.integration.MessagingException;
import org.springframework.integration.util.UpperBound;
import org.springframework.util.Assert;
import java.util.HashSet;
import java.util.Iterator;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.springframework.integration.Message;
import org.springframework.integration.MessagingException;
import org.springframework.integration.util.UpperBound;
import org.springframework.jmx.export.annotation.ManagedAttribute;
import org.springframework.jmx.export.annotation.ManagedResource;
import org.springframework.util.Assert;
/**
* Map-based implementation of {@link MessageStore} and {@link MessageGroupStore}. Enforces a maximum capacity for the
* store.
@@ -34,6 +36,7 @@ import java.util.concurrent.ConcurrentMap;
*
* @since 2.0
*/
@ManagedResource
public class SimpleMessageStore extends AbstractMessageGroupStore implements MessageStore, MessageGroupStore {
private final ConcurrentMap<UUID, Message<?>> idToMessage;
@@ -71,6 +74,11 @@ public class SimpleMessageStore extends AbstractMessageGroupStore implements Mes
public SimpleMessageStore() {
this(0);
}
@ManagedAttribute
public int getMessageCount() {
return idToMessage.size();
}
public <T> Message<T> addMessage(Message<T> message) {
if (!individualUpperBound.tryAcquire(0)) {
@@ -93,7 +101,7 @@ public class SimpleMessageStore extends AbstractMessageGroupStore implements Mes
else
return null;
}
public MessageGroup getMessageGroup(Object groupId) {
Assert.notNull(groupId, "'groupId' must not be null");
SimpleMessageGroup group = groupIdToMessageGroup.get(groupId);

View File

@@ -16,29 +16,32 @@
package org.springframework.integration.store;
import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import org.junit.Test;
import org.springframework.integration.Message;
import org.springframework.integration.message.GenericMessage;
import org.springframework.test.util.ReflectionTestUtils;
import java.util.*;
import static org.junit.Assert.assertEquals;
/**
* @author Dave Syer
*/
public class MessageStoreTests {
@Test
public void shouldRegisterCallbacks() throws Exception {
TestMessageStore store = new TestMessageStore();
store.setExpiryCallbacks(Arrays.<MessageGroupCallback>asList(new MessageGroupCallback() {
store.setExpiryCallbacks(Arrays.<MessageGroupCallback> asList(new MessageGroupCallback() {
public void execute(MessageGroupStore messageGroupStore, MessageGroup group) {
}
}));
assertEquals(1, ((Collection<?>)ReflectionTestUtils.getField(store, "expiryCallbacks")).size());
assertEquals(1, ((Collection<?>) ReflectionTestUtils.getField(store, "expiryCallbacks")).size());
}
@Test
@@ -58,11 +61,30 @@ public class MessageStoreTests {
assertEquals(0, store.getMessageGroup("bar").size());
}
@Test
public void testGroupCount() throws Exception {
TestMessageStore store = new TestMessageStore();
assertEquals(1, store.getMessageGroupCount());
}
@Test
public void testGroupSizes() throws Exception {
TestMessageStore store = new TestMessageStore();
assertEquals(1, store.getMessageCountForAllMessageGroups());
}
@Test
public void testMarkedGroupSizes() throws Exception {
TestMessageStore store = new TestMessageStore();
assertEquals(0, store.getMarkedMessageCountForAllMessageGroups());
}
private static class TestMessageStore extends AbstractMessageGroupStore {
@SuppressWarnings("unchecked")
MessageGroup testMessages = new SimpleMessageGroup(Arrays.asList(new GenericMessage<String>("foo")), "bar");
private boolean removed = false;
@Override
@@ -95,7 +117,7 @@ public class MessageStoreTests {
removed = true;
}
}
}
}