Auto Download: Exponential backoff when file 404s
This commit is contained in:
parent
4f864ab2de
commit
f6d5c780e5
|
@ -11,6 +11,7 @@ import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import de.danoeh.antennapod.core.asynctask.ImageResource;
|
import de.danoeh.antennapod.core.asynctask.ImageResource;
|
||||||
import de.danoeh.antennapod.core.storage.DBReader;
|
import de.danoeh.antennapod.core.storage.DBReader;
|
||||||
|
@ -75,7 +76,13 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr
|
||||||
private List<Chapter> chapters;
|
private List<Chapter> chapters;
|
||||||
private FeedImage image;
|
private FeedImage image;
|
||||||
|
|
||||||
private boolean autoDownload = true;
|
/*
|
||||||
|
* 0: auto download disabled
|
||||||
|
* 1: auto download enabled
|
||||||
|
* > 1: auto download enabled, (approx.) timestamp of the last failed attempt
|
||||||
|
* where last digit denotes the number of failed attempts
|
||||||
|
*/
|
||||||
|
private long autoDownload = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Any tags assigned to this item
|
* Any tags assigned to this item
|
||||||
|
@ -93,7 +100,7 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr
|
||||||
* */
|
* */
|
||||||
public FeedItem(long id, String title, String link, Date pubDate, String paymentLink, long feedId,
|
public FeedItem(long id, String title, String link, Date pubDate, String paymentLink, long feedId,
|
||||||
FlattrStatus flattrStatus, boolean hasChapters, FeedImage image, int state,
|
FlattrStatus flattrStatus, boolean hasChapters, FeedImage image, int state,
|
||||||
String itemIdentifier, boolean autoDownload) {
|
String itemIdentifier, long autoDownload) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.title = title;
|
this.title = title;
|
||||||
this.link = link;
|
this.link = link;
|
||||||
|
@ -162,7 +169,7 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr
|
||||||
FlattrStatus flattrStatus = new FlattrStatus(cursor.getLong(indexFlattrStatus));
|
FlattrStatus flattrStatus = new FlattrStatus(cursor.getLong(indexFlattrStatus));
|
||||||
int state = cursor.getInt(indexRead);
|
int state = cursor.getInt(indexRead);
|
||||||
String itemIdentifier = cursor.getString(indexItemIdentifier);
|
String itemIdentifier = cursor.getString(indexItemIdentifier);
|
||||||
boolean autoDownload = cursor.getInt(indexAutoDownload) > 0;
|
long autoDownload = cursor.getLong(indexAutoDownload);
|
||||||
|
|
||||||
FeedItem item = new FeedItem(id, title, link, pubDate, paymentLink, feedId, flattrStatus,
|
FeedItem item = new FeedItem(id, title, link, pubDate, paymentLink, feedId, flattrStatus,
|
||||||
hasChapters, null, state, itemIdentifier, autoDownload);
|
hasChapters, null, state, itemIdentifier, autoDownload);
|
||||||
|
@ -449,18 +456,37 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAutoDownload(boolean autoDownload) {
|
public void setAutoDownload(boolean autoDownload) {
|
||||||
this.autoDownload = autoDownload;
|
this.autoDownload = autoDownload ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getAutoDownload() {
|
public boolean getAutoDownload() {
|
||||||
return this.autoDownload;
|
return this.autoDownload > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getFailedAutoDownloadAttempts() {
|
||||||
|
if (autoDownload <= 1) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int failedAttempts = (int)(autoDownload % 10);
|
||||||
|
if (failedAttempts == 0) {
|
||||||
|
failedAttempts = 10;
|
||||||
|
}
|
||||||
|
return failedAttempts;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isAutoDownloadable() {
|
public boolean isAutoDownloadable() {
|
||||||
return this.hasMedia() &&
|
if (media == null || media.isPlaying() || media.isDownloaded() || autoDownload == 0) {
|
||||||
false == this.getMedia().isPlaying() &&
|
return false;
|
||||||
false == this.getMedia().isDownloaded() &&
|
}
|
||||||
this.getAutoDownload();
|
if (autoDownload == 1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
int failedAttempts = getFailedAutoDownloadAttempts();
|
||||||
|
double magicValue = 1.767; // 1.767^(10[=#maxNumAttempts]-1) = 168 hours / 7 days
|
||||||
|
int millisecondsInHour = 3600000;
|
||||||
|
long waitingTime = (long) (Math.pow(magicValue, failedAttempts - 1) * millisecondsInHour);
|
||||||
|
long grace = TimeUnit.MINUTES.toMillis(5);
|
||||||
|
return System.currentTimeMillis() > (autoDownload + waitingTime - grace);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -206,8 +206,7 @@ public class DownloadService extends Service {
|
||||||
FeedItem item = media.getItem();
|
FeedItem item = media.getItem();
|
||||||
if (status.getReason() == DownloadError.ERROR_HTTP_DATA_ERROR &&
|
if (status.getReason() == DownloadError.ERROR_HTTP_DATA_ERROR &&
|
||||||
Integer.valueOf(status.getReasonDetailed()) == HttpURLConnection.HTTP_NOT_FOUND) {
|
Integer.valueOf(status.getReasonDetailed()) == HttpURLConnection.HTTP_NOT_FOUND) {
|
||||||
item.setAutoDownload(false); // for event bus
|
DBWriter.saveFeedItemAutoDownloadFailed(item).get();
|
||||||
DBWriter.setFeedItemAutoDownload(item, false);
|
|
||||||
}
|
}
|
||||||
// to make lists reload the failed item, we fake an item update
|
// to make lists reload the failed item, we fake an item update
|
||||||
EventBus.getDefault().post(FeedItemEvent.updated(item));
|
EventBus.getDefault().post(FeedItemEvent.updated(item));
|
||||||
|
|
|
@ -977,11 +977,33 @@ public class DBWriter {
|
||||||
* Sets the 'auto_download'-attribute of specific FeedItem.
|
* Sets the 'auto_download'-attribute of specific FeedItem.
|
||||||
*
|
*
|
||||||
* @param feedItem FeedItem.
|
* @param feedItem FeedItem.
|
||||||
|
* @param autoDownload true enables auto download, false disables it
|
||||||
*/
|
*/
|
||||||
public static Future<?> setFeedItemAutoDownload(final FeedItem feedItem,
|
public static Future<?> setFeedItemAutoDownload(final FeedItem feedItem,
|
||||||
final boolean autoDownload) {
|
final boolean autoDownload) {
|
||||||
Log.d(TAG, "FeedItem[id=" + feedItem.getId() + "] SET auto_download " + autoDownload);
|
|
||||||
return dbExec.submit(() -> {
|
return dbExec.submit(() -> {
|
||||||
|
final PodDBAdapter adapter = PodDBAdapter.getInstance();
|
||||||
|
adapter.open();
|
||||||
|
adapter.setFeedItemAutoDownload(feedItem, autoDownload ? 1 : 0);
|
||||||
|
adapter.close();
|
||||||
|
EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Future<?> saveFeedItemAutoDownloadFailed(final FeedItem feedItem) {
|
||||||
|
return dbExec.submit(() -> {
|
||||||
|
int failedAttempts = feedItem.getFailedAutoDownloadAttempts() + 1;
|
||||||
|
Log.d(TAG, "failedAttempts: " + failedAttempts);
|
||||||
|
long autoDownload;
|
||||||
|
if(!feedItem.getAutoDownload() || failedAttempts >= 10) {
|
||||||
|
autoDownload = 0; // giving up, disable auto download
|
||||||
|
feedItem.setAutoDownload(false);
|
||||||
|
} else {
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
autoDownload = (now / 10) * 10 + failedAttempts;
|
||||||
|
Log.d(TAG, "now: " + now);
|
||||||
|
Log.d(TAG, "autoDownload: " + autoDownload);
|
||||||
|
}
|
||||||
final PodDBAdapter adapter = PodDBAdapter.getInstance();
|
final PodDBAdapter adapter = PodDBAdapter.getInstance();
|
||||||
adapter.open();
|
adapter.open();
|
||||||
adapter.setFeedItemAutoDownload(feedItem, autoDownload);
|
adapter.setFeedItemAutoDownload(feedItem, autoDownload);
|
||||||
|
@ -992,7 +1014,8 @@ public class DBWriter {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the 'auto_download'-attribute of specific FeedItem.
|
* Sets the 'auto_download'-attribute of specific FeedItem.
|
||||||
* @param feed This feed's episodes will be processed.
|
*
|
||||||
|
* @param feed This feed's episodes will be processed.
|
||||||
* @param autoDownload If true, auto download will be enabled for the feed's episodes. Else,
|
* @param autoDownload If true, auto download will be enabled for the feed's episodes. Else,
|
||||||
*/
|
*/
|
||||||
public static Future<?> setFeedsItemsAutoDownload(final Feed feed,
|
public static Future<?> setFeedsItemsAutoDownload(final Feed feed,
|
||||||
|
|
|
@ -794,7 +794,7 @@ public class PodDBAdapter {
|
||||||
return status.getId();
|
return status.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFeedItemAutoDownload(FeedItem feedItem, boolean autoDownload) {
|
public void setFeedItemAutoDownload(FeedItem feedItem, long autoDownload) {
|
||||||
ContentValues values = new ContentValues();
|
ContentValues values = new ContentValues();
|
||||||
values.put(KEY_AUTO_DOWNLOAD, autoDownload);
|
values.put(KEY_AUTO_DOWNLOAD, autoDownload);
|
||||||
db.update(TABLE_NAME_FEED_ITEMS, values, KEY_ID + "=?",
|
db.update(TABLE_NAME_FEED_ITEMS, values, KEY_ID + "=?",
|
||||||
|
|
Loading…
Reference in New Issue