Don’t store posts by recipient, generate them on the fly.
authorDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Wed, 17 Sep 2014 20:02:19 +0000 (22:02 +0200)
committerDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Wed, 17 Sep 2014 20:03:10 +0000 (22:03 +0200)
Yes, this will result in worse performance of these methods as long as
there is no real database behind it. But there will be a database
behind all this. Some day.

src/main/java/net/pterodactylus/sone/database/memory/MemoryDatabase.java
src/test/java/net/pterodactylus/sone/database/memory/MemoryDatabaseTest.java

index cd3be84..0b2c5a2 100644 (file)
@@ -19,6 +19,7 @@ package net.pterodactylus.sone.database.memory;
 
 import static com.google.common.base.Optional.fromNullable;
 import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.FluentIterable.from;
 import static net.pterodactylus.sone.data.Reply.TIME_COMPARATOR;
 
 import java.util.ArrayList;
@@ -52,6 +53,7 @@ import net.pterodactylus.util.config.Configuration;
 import net.pterodactylus.util.config.ConfigurationException;
 
 import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
 import com.google.common.collect.HashMultimap;
 import com.google.common.collect.Multimap;
 import com.google.common.collect.SortedSetMultimap;
@@ -83,9 +85,6 @@ public class MemoryDatabase extends AbstractService implements Database {
        /** All posts by their Sones. */
        private final Multimap<String, Post> sonePosts = HashMultimap.create();
 
-       /** All posts by their recipient. */
-       private final Multimap<String, Post> recipientPosts = HashMultimap.create();
-
        /** Whether posts are known. */
        private final Set<String> knownPosts = new HashSet<String>();
 
@@ -195,11 +194,15 @@ public class MemoryDatabase extends AbstractService implements Database {
 
        /** {@inheritDocs} */
        @Override
-       public Collection<Post> getDirectedPosts(String recipientId) {
+       public Collection<Post> getDirectedPosts(final String recipientId) {
                lock.readLock().lock();
                try {
-                       Collection<Post> posts = recipientPosts.get(recipientId);
-                       return (posts == null) ? Collections.<Post>emptySet() : new HashSet<Post>(posts);
+                       return from(sonePosts.values()).filter(new Predicate<Post>() {
+                               @Override
+                               public boolean apply(Post post) {
+                                       return post.getRecipientId().asSet().contains(recipientId);
+                               }
+                       }).toSet();
                } finally {
                        lock.readLock().unlock();
                }
@@ -227,9 +230,6 @@ public class MemoryDatabase extends AbstractService implements Database {
                try {
                        allPosts.put(post.getId(), post);
                        getPostsFrom(post.getSone().getId()).add(post);
-                       if (post.getRecipientId().isPresent()) {
-                               getPostsTo(post.getRecipientId().get()).add(post);
-                       }
                } finally {
                        lock.writeLock().unlock();
                }
@@ -243,9 +243,6 @@ public class MemoryDatabase extends AbstractService implements Database {
                try {
                        allPosts.remove(post.getId());
                        getPostsFrom(post.getSone().getId()).remove(post);
-                       if (post.getRecipientId().isPresent()) {
-                               getPostsTo(post.getRecipientId().get()).remove(post);
-                       }
                        post.getSone().removePost(post);
                } finally {
                        lock.writeLock().unlock();
@@ -269,18 +266,12 @@ public class MemoryDatabase extends AbstractService implements Database {
                        Collection<Post> oldPosts = getPostsFrom(sone.getId());
                        for (Post post : oldPosts) {
                                allPosts.remove(post.getId());
-                               if (post.getRecipientId().isPresent()) {
-                                       getPostsTo(post.getRecipientId().get()).remove(post);
-                               }
                        }
 
                        /* add new posts. */
                        getPostsFrom(sone.getId()).addAll(posts);
                        for (Post post : posts) {
                                allPosts.put(post.getId(), post);
-                               if (post.getRecipientId().isPresent()) {
-                                       getPostsTo(post.getRecipientId().get()).add(post);
-                               }
                        }
                } finally {
                        lock.writeLock().unlock();
@@ -297,9 +288,6 @@ public class MemoryDatabase extends AbstractService implements Database {
                        getPostsFrom(sone.getId()).clear();
                        for (Post post : sone.getPosts()) {
                                allPosts.remove(post.getId());
-                               if (post.getRecipientId().isPresent()) {
-                                       getPostsTo(post.getRecipientId().get()).remove(post);
-                               }
                        }
                } finally {
                        lock.writeLock().unlock();
@@ -615,23 +603,6 @@ public class MemoryDatabase extends AbstractService implements Database {
                }
        }
 
-       /**
-        * Gets all posts that are directed the given Sone, creating a new collection
-        * if there is none yet.
-        *
-        * @param recipientId
-        *              The ID of the Sone to get the posts for
-        * @return All posts
-        */
-       private Collection<Post> getPostsTo(String recipientId) {
-               lock.readLock().lock();
-               try {
-                       return recipientPosts.get(recipientId);
-               } finally {
-                       lock.readLock().unlock();
-               }
-       }
-
        /** Loads the known posts. */
        private void loadKnownPosts() {
                lock.writeLock().lock();
index 74c58ca..cad0a23 100644 (file)
@@ -20,13 +20,17 @@ package net.pterodactylus.sone.database.memory;
 import static com.google.common.base.Optional.of;
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.contains;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
 import net.pterodactylus.sone.data.Album;
 import net.pterodactylus.sone.data.AlbumImpl;
+import net.pterodactylus.sone.data.Post;
 import net.pterodactylus.sone.data.Sone;
 
 import com.google.common.base.Optional;
+import org.junit.Before;
 import org.junit.Test;
 
 /**
@@ -36,7 +40,30 @@ import org.junit.Test;
  */
 public class MemoryDatabaseTest {
 
+       private static final String SONE_ID = "sone";
+       private static final String RECIPIENT_ID = "recipient";
        private final MemoryDatabase memoryDatabase = new MemoryDatabase(null, null);
+       private final Sone sone = mock(Sone.class);
+
+       @Before
+       public void setupSone() {
+               when(sone.getId()).thenReturn(SONE_ID);
+       }
+
+       @Test
+       public void postRecipientsAreDetectedCorrectly() {
+               Post postWithRecipient = mock(Post.class);
+               when(postWithRecipient.getSone()).thenReturn(sone);
+               when(postWithRecipient.getRecipientId()).thenReturn(of(RECIPIENT_ID));
+               memoryDatabase.storePost(postWithRecipient);
+               Post postWithoutRecipient = mock(Post.class);
+               when(postWithoutRecipient.getSone()).thenReturn(sone);
+               when(postWithoutRecipient.getRecipientId()).thenReturn(
+                               Optional.<String>absent());
+               memoryDatabase.storePost(postWithoutRecipient);
+               assertThat(memoryDatabase.getDirectedPosts(RECIPIENT_ID),
+                               contains(postWithRecipient));
+       }
 
        @Test
        public void testBasicAlbumFunctionality() {