]> uap-core.de Git - rssreader.git/commitdiff
implement background sync
authorOlaf Wintermann <olaf.wintermann@gmail.com>
Sun, 7 Sep 2025 12:33:09 +0000 (14:33 +0200)
committerOlaf Wintermann <olaf.wintermann@gmail.com>
Sun, 7 Sep 2025 12:33:09 +0000 (14:33 +0200)
rss-application/src/main/kotlin/de/unixwork/rssreader/App.kt
rss-application/src/main/kotlin/de/unixwork/rssreader/Database.kt
rss-application/src/main/kotlin/de/unixwork/rssreader/SyncJob.kt

index 33eeec18a7be5c581f4b6278ee39cf480f33fd1b..ee096282df54f608c7aadc80460045af6b3d1fc9 100644 (file)
@@ -3,10 +3,18 @@ package de.unixwork.rssreader
 import de.unixwork.ui.Application
 import de.unixwork.ui.ToolbarPosition
 import de.unixwork.ui.Toolkit
+import de.unixwork.ui.kotlin.ToolkitDispatcher
 import de.unixwork.ui.kotlin.toolbarItem
 import de.unixwork.ui.kotlin.addToolbarDefault
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.GlobalScope
+import kotlinx.coroutines.IO
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
 
 class App : Application {
+    var window: MainWindow? = null
+
     init {
         initToolbar()
     }
@@ -25,13 +33,41 @@ class App : Application {
     }
 
     override fun startup() {
-        val window = MainWindow()
-        window.show()
+        window = MainWindow()
+        window?.show()
+
+        backgroundSync(10 * 1000L)
     }
 
     override fun shutdown() {
         System.exit(0)
     }
+
+    fun backgroundSync(delayedStart: Long = 0) {
+        GlobalScope.launch(Dispatchers.IO) {
+            delay(delayedStart)
+
+            while(true) {
+                println("Background sync")
+                try {
+                    val pending = Database.getPendingFeeds(1 * 60)
+                    SyncJob { pending }.syncBlocking()
+                    GlobalScope.launch(ToolkitDispatcher) {
+                        window!!.sourceList.invalidateCache()
+                        window!!.sourceList.reloadStatus()
+                        window!!.feedList.reloadCurrentFeed()
+                    }
+                } catch (e: Exception) {
+                    e.printStackTrace()
+                }
+                println("Background sync done")
+
+                // TODO: check time until next feed needs sync
+
+                delay(60 * 1000L)
+            }
+        }
+    }
 }
 
 fun main() {
index e6677895e0acef61c85be9b4cf4deeda563ad34f..85b6b00c92c63b109f8d3269bf946b427c5a8c5e 100644 (file)
@@ -296,27 +296,30 @@ object Database {
         return feeds
     }
 
-    public fun getPendingFeeds() : MutableList<Feed> {
+    public fun getPendingFeeds(defaultInterval: Int) : MutableList<Feed> {
         val feeds = mutableListOf<Feed>()
 
         dataSource.connection.use { conn ->
             conn.prepareStatement("""
             select f.* from feeds f 
             inner join feedcollections c on f.feedcollection_id = c.feedcollection_id 
-            where datediff(ss, coalesce(last_update, '1970-01-01'), now()) > case when c.update_interval > 0 then c.update_interval else 60 end
+            where datediff(ss, now(), coalesce(last_update, '1970-01-01')) > case when c.update_interval > 0 then c.update_interval else ? end
             """.trimIndent()).use { stmt ->
+                stmt.setInt(1, defaultInterval)
                 stmt.executeQuery().use { rs ->
-                    val id = rs.getInt("feed_id")
-                    val feedCollectionId = rs.getInt("feedcollection_id")
-                    val url = rs.getString("url")
-                    val authUser = rs.getString("auth_user")
-                    val authPassword = rs.getString("auth_password")
-                    val certPath = rs.getString("certpath")
-                    val feed = Feed(id, feedCollectionId, url)
-                    feed.user = authUser
-                    feed.password = authPassword
-                    feed.certpath = certPath
-                    feeds.add(feed)
+                    while(rs.next()) {
+                        val id = rs.getInt("feed_id")
+                        val feedCollectionId = rs.getInt("feedcollection_id")
+                        val url = rs.getString("url")
+                        val authUser = rs.getString("auth_user")
+                        val authPassword = rs.getString("auth_password")
+                        val certPath = rs.getString("certpath")
+                        val feed = Feed(id, feedCollectionId, url)
+                        feed.user = authUser
+                        feed.password = authPassword
+                        feed.certpath = certPath
+                        feeds.add(feed)
+                    }
                 }
             }
         }
index f205f7dcd5384243db7080b8b25e93fde332da81..a1c81f38bb3feaac892dc437e5abce220a1b243c 100644 (file)
@@ -8,7 +8,9 @@ import kotlinx.coroutines.GlobalScope
 import kotlinx.coroutines.IO
 import kotlinx.coroutines.async
 import kotlinx.coroutines.awaitAll
+import kotlinx.coroutines.coroutineScope
 import kotlinx.coroutines.launch
+import kotlinx.coroutines.runBlocking
 import java.net.URI
 import java.net.http.HttpClient
 import java.net.http.HttpRequest
@@ -21,10 +23,24 @@ class SyncJob(feeds: () -> List<Feed>) {
     fun sync(completion: () -> Unit = {}) {
         GlobalScope.launch(Dispatchers.IO) {
             val feeds = getFeeds()
+            syncFeeds(feeds)
+            GlobalScope.launch(completionContext) {
+                completion()
+            }
+        }
+    }
+
+    fun syncBlocking() {
+        runBlocking {
+            syncFeeds(getFeeds())
+        }
+    }
 
+    private suspend fun syncFeeds(feeds: List<Feed>) {
+        coroutineScope {
             val client = HttpClient.newBuilder().build()
             val jobs = feeds.map { feed ->
-                async {
+                async(Dispatchers.IO) {
                     try {
                         val requestBuilder = HttpRequest.newBuilder()
                             .uri(URI(feed.uri))
@@ -86,10 +102,6 @@ class SyncJob(feeds: () -> List<Feed>) {
                 }
             }
             jobs.awaitAll()
-
-            GlobalScope.launch(completionContext) {
-                completion()
-            }
         }
     }
 }
\ No newline at end of file