✨ Only save known posts and replies once per second
authorDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Tue, 10 Sep 2019 10:11:40 +0000 (12:11 +0200)
committerDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Tue, 10 Sep 2019 10:11:40 +0000 (12:11 +0200)
src/main/java/net/pterodactylus/sone/database/memory/MemoryDatabase.kt
src/test/kotlin/net/pterodactylus/sone/database/memory/MemoryDatabaseTest.kt

index a9459e8..857560e 100644 (file)
@@ -41,7 +41,7 @@ import net.pterodactylus.sone.database.ImageBuilder
 import net.pterodactylus.sone.database.PostBuilder
 import net.pterodactylus.sone.database.PostDatabase
 import net.pterodactylus.sone.database.PostReplyBuilder
-import net.pterodactylus.sone.utils.unit
+import net.pterodactylus.sone.utils.*
 import net.pterodactylus.util.config.Configuration
 import net.pterodactylus.util.config.ConfigurationException
 import java.util.concurrent.locks.ReentrantReadWriteLock
@@ -71,6 +71,8 @@ class MemoryDatabase @Inject constructor(private val configuration: Configuratio
        private val memoryBookmarkDatabase = MemoryBookmarkDatabase(this, configurationLoader)
        private val memoryFriendDatabase = MemoryFriendDatabase(configurationLoader)
        private val saveRateLimiter: RateLimiter = RateLimiter.create(1.0)
+       private val saveKnownPostsRateLimiter: RateLimiter = RateLimiter.create(1.0)
+       private val saveKnownPostRepliesRateLimiter: RateLimiter = RateLimiter.create(1.0)
 
        override val soneLoader get() = this::getSone
 
@@ -314,15 +316,17 @@ class MemoryDatabase @Inject constructor(private val configuration: Configuratio
                                        }
 
        private fun saveKnownPosts() =
-                       try {
-                               readLock.withLock {
-                                       knownPosts.forEachIndexed { index, knownPostId ->
-                                               configuration.getStringValue("KnownPosts/$index/ID").value = knownPostId
+                       saveKnownPostsRateLimiter.tryAcquire().ifTrue {
+                               try {
+                                       readLock.withLock {
+                                               knownPosts.forEachIndexed { index, knownPostId ->
+                                                       configuration.getStringValue("KnownPosts/$index/ID").value = knownPostId
+                                               }
+                                               configuration.getStringValue("KnownPosts/${knownPosts.size}/ID").value = null
                                        }
-                                       configuration.getStringValue("KnownPosts/${knownPosts.size}/ID").value = null
+                               } catch (ce1: ConfigurationException) {
+                                       throw DatabaseException("Could not save database.", ce1)
                                }
-                       } catch (ce1: ConfigurationException) {
-                               throw DatabaseException("Could not save database.", ce1)
                        }
 
        private fun loadKnownPostReplies(): Unit =
@@ -334,15 +338,17 @@ class MemoryDatabase @Inject constructor(private val configuration: Configuratio
                        }
 
        private fun saveKnownPostReplies() =
-                       try {
-                               readLock.withLock {
-                                       knownPostReplies.forEachIndexed { index, knownPostReply ->
-                                               configuration.getStringValue("KnownReplies/$index/ID").value = knownPostReply
+                       saveKnownPostRepliesRateLimiter.tryAcquire().ifTrue {
+                               try {
+                                       readLock.withLock {
+                                               knownPostReplies.forEachIndexed { index, knownPostReply ->
+                                                       configuration.getStringValue("KnownReplies/$index/ID").value = knownPostReply
+                                               }
+                                               configuration.getStringValue("KnownReplies/${knownPostReplies.size}/ID").value = null
                                        }
-                                       configuration.getStringValue("KnownReplies/${knownPostReplies.size}/ID").value = null
+                               } catch (ce1: ConfigurationException) {
+                                       throw DatabaseException("Could not save database.", ce1)
                                }
-                       } catch (ce1: ConfigurationException) {
-                               throw DatabaseException("Could not save database.", ce1)
                        }
 
 }
index 4d7a105..46796ab 100644 (file)
@@ -417,6 +417,28 @@ class MemoryDatabaseTest {
                verify(configuration.getStringValue("KnownPosts/0/ID"), times(1)).value = null
        }
 
+       @Test
+       @Dirty("the rate limiter should be mocked")
+       fun `setting posts as knows twice in a row only saves the database once`() {
+               prepareConfigurationValues()
+               val post = mock<Post>()
+               whenever(post.id).thenReturn("post-id")
+               memoryDatabase.setPostKnown(post, true)
+               memoryDatabase.setPostKnown(post, true)
+               verify(configuration, times(1)).getStringValue("KnownPosts/1/ID")
+       }
+
+       @Test
+       @Dirty("the rate limiter should be mocked")
+       fun `setting post replies as knows twice in a row only saves the database once`() {
+               prepareConfigurationValues()
+               val postReply = mock<PostReply>()
+               whenever(postReply.id).thenReturn("post-reply-id")
+               memoryDatabase.setPostReplyKnown(postReply, true)
+               memoryDatabase.setPostReplyKnown(postReply, true)
+               verify(configuration, times(1)).getStringValue("KnownReplies/1/ID")
+       }
+
 }
 
 private const val SONE_ID = "sone"