Sync after refreshing (#7475)

- Enables users to manually trigger sync
- Makes sure that we actually refresh when a new feed arrives:
Previously, we might request the feed to be refreshed but then don't
actually wait for it to be completed because the refresh service
wouldn't start up quickly enough.

This makes sure that we do not try to sync again before the refresh
actually went through, even if the sync service is called multiple times.
This commit is contained in:
ByteHamster 2024-11-01 10:29:11 +01:00 committed by GitHub
parent 4a92a5e019
commit f30cdf0e80
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 31 additions and 25 deletions

View File

@ -24,6 +24,7 @@ import de.danoeh.antennapod.net.download.service.feed.remote.Downloader;
import de.danoeh.antennapod.net.download.service.feed.remote.FeedParserTask; import de.danoeh.antennapod.net.download.service.feed.remote.FeedParserTask;
import de.danoeh.antennapod.net.download.serviceinterface.AutoDownloadManager; import de.danoeh.antennapod.net.download.serviceinterface.AutoDownloadManager;
import de.danoeh.antennapod.net.download.serviceinterface.DownloadRequestCreator; import de.danoeh.antennapod.net.download.serviceinterface.DownloadRequestCreator;
import de.danoeh.antennapod.net.sync.serviceinterface.SynchronizationQueue;
import de.danoeh.antennapod.storage.database.DBReader; import de.danoeh.antennapod.storage.database.DBReader;
import de.danoeh.antennapod.storage.database.FeedDatabaseWriter; import de.danoeh.antennapod.storage.database.FeedDatabaseWriter;
import de.danoeh.antennapod.storage.database.DBWriter; import de.danoeh.antennapod.storage.database.DBWriter;
@ -103,6 +104,7 @@ public class FeedUpdateWorker extends Worker {
NonSubscribedFeedsCleaner.deleteOldNonSubscribedFeeds(getApplicationContext()); NonSubscribedFeedsCleaner.deleteOldNonSubscribedFeeds(getApplicationContext());
AutoDownloadManager.getInstance().autodownloadUndownloadedItems(getApplicationContext()); AutoDownloadManager.getInstance().autodownloadUndownloadedItems(getApplicationContext());
notificationManager.cancel(R.id.notification_updating_feeds); notificationManager.cancel(R.id.notification_updating_feeds);
SynchronizationQueue.getInstance().syncImmediately();
return Result.success(); return Result.success();
} }

View File

@ -15,7 +15,6 @@ import androidx.core.content.ContextCompat;
import androidx.core.util.Pair; import androidx.core.util.Pair;
import androidx.work.Worker; import androidx.work.Worker;
import androidx.work.WorkerParameters; import androidx.work.WorkerParameters;
import de.danoeh.antennapod.event.FeedUpdateRunningEvent;
import de.danoeh.antennapod.event.MessageEvent; import de.danoeh.antennapod.event.MessageEvent;
import de.danoeh.antennapod.event.SyncServiceEvent; import de.danoeh.antennapod.event.SyncServiceEvent;
import de.danoeh.antennapod.model.feed.Feed; import de.danoeh.antennapod.model.feed.Feed;
@ -70,12 +69,21 @@ public class SyncService extends Worker {
return Result.success(); return Result.success();
} }
SynchronizationSettings.updateLastSynchronizationAttempt(); if (currentlyActive) {
return Result.success();
}
currentlyActive = true; currentlyActive = true;
SynchronizationSettings.updateLastSynchronizationAttempt();
try { try {
activeSyncProvider.login(); activeSyncProvider.login();
syncSubscriptions(activeSyncProvider); syncSubscriptions(activeSyncProvider);
waitForDownloadServiceCompleted(); if (someFeedWasNotRefreshedYet()) {
// Note that this service might get called several times before the FeedUpdate completes
Log.d(TAG, "Found new subscriptions. Need to refresh them before syncing episode actions");
EventBus.getDefault().postSticky(new SyncServiceEvent(R.string.sync_status_wait_for_downloads));
FeedUpdateManager.getInstance().runOnce(getApplicationContext());
return Result.success();
}
syncEpisodeActions(activeSyncProvider); syncEpisodeActions(activeSyncProvider);
activeSyncProvider.logout(); activeSyncProvider.logout();
clearErrorNotifications(); clearErrorNotifications();
@ -102,6 +110,15 @@ public class SyncService extends Worker {
} }
} }
private boolean someFeedWasNotRefreshedYet() {
for (Feed feed : DBReader.getFeedList()) {
if (feed.getLastRefreshAttempt() == 0) {
return true;
}
}
return false;
}
/* package-private */ static boolean isCurrentlyActive() { /* package-private */ static boolean isCurrentlyActive() {
return currentlyActive; return currentlyActive;
} }
@ -125,8 +142,7 @@ public class SyncService extends Worker {
if (!UrlChecker.containsUrl(localSubscriptions, downloadUrl) && !queuedRemovedFeeds.contains(downloadUrl)) { if (!UrlChecker.containsUrl(localSubscriptions, downloadUrl) && !queuedRemovedFeeds.contains(downloadUrl)) {
Feed feed = new Feed(downloadUrl, null, "Unknown podcast"); Feed feed = new Feed(downloadUrl, null, "Unknown podcast");
feed.setItems(Collections.emptyList()); feed.setItems(Collections.emptyList());
Feed newFeed = FeedDatabaseWriter.updateFeed(getApplicationContext(), feed, false); FeedDatabaseWriter.updateFeed(getApplicationContext(), feed, false);
FeedUpdateManager.getInstance().runOnce(getApplicationContext(), newFeed);
} }
} }
@ -140,11 +156,15 @@ public class SyncService extends Worker {
if (lastSync == 0) { if (lastSync == 0) {
Log.d(TAG, "First sync. Adding all local subscriptions."); Log.d(TAG, "First sync. Adding all local subscriptions.");
queuedAddedFeeds = localSubscriptions; queuedAddedFeeds = localSubscriptions;
queuedAddedFeeds.removeAll(subscriptionChanges.getAdded());
queuedRemovedFeeds.removeAll(subscriptionChanges.getRemoved());
} }
if (!queuedAddedFeeds.isEmpty() || !queuedRemovedFeeds.isEmpty()) { queuedAddedFeeds.removeAll(subscriptionChanges.getAdded());
queuedRemovedFeeds.removeAll(subscriptionChanges.getRemoved());
if (queuedAddedFeeds.isEmpty() && queuedRemovedFeeds.isEmpty()) {
Log.d(TAG, "No feeds to add or remove from server");
synchronizationQueueStorage.clearFeedQueues();
} else {
Log.d(TAG, "Added: " + StringUtils.join(queuedAddedFeeds, ", ")); Log.d(TAG, "Added: " + StringUtils.join(queuedAddedFeeds, ", "));
Log.d(TAG, "Removed: " + StringUtils.join(queuedRemovedFeeds, ", ")); Log.d(TAG, "Removed: " + StringUtils.join(queuedRemovedFeeds, ", "));
@ -161,22 +181,6 @@ public class SyncService extends Worker {
SynchronizationSettings.setLastSubscriptionSynchronizationAttemptTimestamp(newTimeStamp); SynchronizationSettings.setLastSubscriptionSynchronizationAttemptTimestamp(newTimeStamp);
} }
private void waitForDownloadServiceCompleted() {
EventBus.getDefault().postSticky(new SyncServiceEvent(R.string.sync_status_wait_for_downloads));
try {
while (true) {
//noinspection BusyWait
Thread.sleep(1000);
FeedUpdateRunningEvent event = EventBus.getDefault().getStickyEvent(FeedUpdateRunningEvent.class);
if (event == null || !event.isFeedUpdateRunning) {
return;
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void syncEpisodeActions(ISyncService syncServiceImpl) throws SyncServiceException { private void syncEpisodeActions(ISyncService syncServiceImpl) throws SyncServiceException {
final long lastSync = SynchronizationSettings.getLastEpisodeActionSynchronizationTimestamp(); final long lastSync = SynchronizationSettings.getLastEpisodeActionSynchronizationTimestamp();
EventBus.getDefault().postSticky(new SyncServiceEvent(R.string.sync_status_episodes_download)); EventBus.getDefault().postSticky(new SyncServiceEvent(R.string.sync_status_episodes_download));

View File

@ -571,7 +571,7 @@
<string name="sync_status_episodes_download">Downloading episode changes…</string> <string name="sync_status_episodes_download">Downloading episode changes…</string>
<string name="sync_status_upload_played">Uploading played status…</string> <string name="sync_status_upload_played">Uploading played status…</string>
<string name="sync_status_subscriptions">Synchronizing subscriptions…</string> <string name="sync_status_subscriptions">Synchronizing subscriptions…</string>
<string name="sync_status_wait_for_downloads">Waiting for downloads to complete</string> <string name="sync_status_wait_for_downloads">Waiting for subscriptions refresh</string>
<string name="sync_status_success">Synchronization successful</string> <string name="sync_status_success">Synchronization successful</string>
<string name="sync_status_error">Synchronization failed</string> <string name="sync_status_error">Synchronization failed</string>