From 7314f3584495748eab2ef19a93d3139d51552915 Mon Sep 17 00:00:00 2001 From: Charlotte Van Petegem Date: Tue, 21 Jun 2022 22:37:27 +0200 Subject: [PATCH] Retry fetches of resource index a few times with exponential backoff (#395) --- .../me/vanpetegem/accentor/api/album/Album.kt | 35 ++++++++++--------- .../vanpetegem/accentor/api/artist/Artist.kt | 35 ++++++++++--------- .../api/codecconversion/CodecConversion.kt | 35 ++++++++++--------- .../me/vanpetegem/accentor/api/plays/Play.kt | 35 ++++++++++--------- .../me/vanpetegem/accentor/api/track/Track.kt | 35 ++++++++++--------- .../me/vanpetegem/accentor/api/user/User.kt | 35 ++++++++++--------- .../me/vanpetegem/accentor/api/util/Util.kt | 16 +++++++++ 7 files changed, 130 insertions(+), 96 deletions(-) create mode 100644 app/src/main/java/me/vanpetegem/accentor/api/util/Util.kt diff --git a/app/src/main/java/me/vanpetegem/accentor/api/album/Album.kt b/app/src/main/java/me/vanpetegem/accentor/api/album/Album.kt index c437cfe3..4e455bcc 100644 --- a/app/src/main/java/me/vanpetegem/accentor/api/album/Album.kt +++ b/app/src/main/java/me/vanpetegem/accentor/api/album/Album.kt @@ -1,6 +1,7 @@ package me.vanpetegem.accentor.api.album import com.github.kittinunf.fuel.httpGet +import me.vanpetegem.accentor.api.util.retry import me.vanpetegem.accentor.data.albums.ApiAlbum import me.vanpetegem.accentor.data.authentication.AuthenticationData import me.vanpetegem.accentor.util.Result @@ -10,22 +11,24 @@ fun index(server: String, authenticationData: AuthenticationData): Sequence>? { - return "$server/api/albums".httpGet(listOf(Pair("page", page))) - .set("Accept", "application/json") - .set("X-Secret", authenticationData.secret) - .set("X-Device-Id", authenticationData.deviceId) - .responseObject>().third - .fold( - { a: List -> - if (a.isEmpty()) { - null - } else { - page++ - Result.Success(a) - } - }, - { e: Throwable -> Result.Error(Exception("Error getting albums", e)) } - ) + return retry(5) { + "$server/api/albums".httpGet(listOf(Pair("page", page))) + .set("Accept", "application/json") + .set("X-Secret", authenticationData.secret) + .set("X-Device-Id", authenticationData.deviceId) + .responseObject>().third + .fold( + { a: List -> + if (a.isEmpty()) { + null + } else { + page++ + Result.Success(a) + } + }, + { e: Throwable -> Result.Error(Exception("Error getting albums", e)) } + ) + } } return generateSequence { doFetch() } diff --git a/app/src/main/java/me/vanpetegem/accentor/api/artist/Artist.kt b/app/src/main/java/me/vanpetegem/accentor/api/artist/Artist.kt index 10c2545c..05bc9a19 100644 --- a/app/src/main/java/me/vanpetegem/accentor/api/artist/Artist.kt +++ b/app/src/main/java/me/vanpetegem/accentor/api/artist/Artist.kt @@ -1,6 +1,7 @@ package me.vanpetegem.accentor.api.artist import com.github.kittinunf.fuel.httpGet +import me.vanpetegem.accentor.api.util.retry import me.vanpetegem.accentor.data.artists.ApiArtist import me.vanpetegem.accentor.data.authentication.AuthenticationData import me.vanpetegem.accentor.util.Result @@ -10,22 +11,24 @@ fun index(server: String, authenticationData: AuthenticationData): Sequence>? { - return "$server/api/artists".httpGet(listOf(Pair("page", page))) - .set("Accept", "application/json") - .set("X-Secret", authenticationData.secret) - .set("X-Device-Id", authenticationData.deviceId) - .responseObject>().third - .fold( - { a: List -> - if (a.isEmpty()) { - null - } else { - page++ - Result.Success(a) - } - }, - { e: Throwable -> Result.Error(Exception("Error getting artists", e)) } - ) + return retry(5) { + "$server/api/artists".httpGet(listOf(Pair("page", page))) + .set("Accept", "application/json") + .set("X-Secret", authenticationData.secret) + .set("X-Device-Id", authenticationData.deviceId) + .responseObject>().third + .fold( + { a: List -> + if (a.isEmpty()) { + null + } else { + page++ + Result.Success(a) + } + }, + { e: Throwable -> Result.Error(Exception("Error getting artists", e)) } + ) + } } return generateSequence { doFetch() } diff --git a/app/src/main/java/me/vanpetegem/accentor/api/codecconversion/CodecConversion.kt b/app/src/main/java/me/vanpetegem/accentor/api/codecconversion/CodecConversion.kt index 18d89431..7fdd0ff6 100644 --- a/app/src/main/java/me/vanpetegem/accentor/api/codecconversion/CodecConversion.kt +++ b/app/src/main/java/me/vanpetegem/accentor/api/codecconversion/CodecConversion.kt @@ -1,6 +1,7 @@ package me.vanpetegem.accentor.api.codecconversion import com.github.kittinunf.fuel.httpGet +import me.vanpetegem.accentor.api.util.retry import me.vanpetegem.accentor.data.authentication.AuthenticationData import me.vanpetegem.accentor.data.codecconversions.ApiCodecConversion import me.vanpetegem.accentor.util.Result @@ -10,22 +11,24 @@ fun index(server: String, authenticationData: AuthenticationData): Sequence>? { - return "$server/api/codec_conversions".httpGet(listOf(Pair("page", page))) - .set("Accept", "application/json") - .set("X-Secret", authenticationData.secret) - .set("X-Device-Id", authenticationData.deviceId) - .responseObject>().third - .fold( - { c: List -> - if (c.isEmpty()) { - null - } else { - page++ - Result.Success(c) - } - }, - { e: Throwable -> Result.Error(Exception("Error getting codec conversions", e)) } - ) + return retry(5) { + "$server/api/codec_conversions".httpGet(listOf(Pair("page", page))) + .set("Accept", "application/json") + .set("X-Secret", authenticationData.secret) + .set("X-Device-Id", authenticationData.deviceId) + .responseObject>().third + .fold( + { c: List -> + if (c.isEmpty()) { + null + } else { + page++ + Result.Success(c) + } + }, + { e: Throwable -> Result.Error(Exception("Error getting codec conversions", e)) } + ) + } } return generateSequence { doFetch() } diff --git a/app/src/main/java/me/vanpetegem/accentor/api/plays/Play.kt b/app/src/main/java/me/vanpetegem/accentor/api/plays/Play.kt index aa87b2b2..05759214 100644 --- a/app/src/main/java/me/vanpetegem/accentor/api/plays/Play.kt +++ b/app/src/main/java/me/vanpetegem/accentor/api/plays/Play.kt @@ -3,6 +3,7 @@ package me.vanpetegem.accentor.api.plays import com.github.kittinunf.fuel.httpGet import com.github.kittinunf.fuel.httpPost import java.time.Instant +import me.vanpetegem.accentor.api.util.retry import me.vanpetegem.accentor.data.authentication.AuthenticationData import me.vanpetegem.accentor.data.plays.ApiPlay import me.vanpetegem.accentor.util.Result @@ -29,22 +30,24 @@ fun index(server: String, authenticationData: AuthenticationData): Sequence>? { - return "$server/api/plays".httpGet(listOf(Pair("page", page))) - .set("Accept", "application/json") - .set("X-Secret", authenticationData.secret) - .set("X-Device-Id", authenticationData.deviceId) - .responseObject>().third - .fold( - { p: List -> - if (p.isEmpty()) { - null - } else { - page++ - Result.Success(p) - } - }, - { e: Throwable -> Result.Error(Exception("Error getting plays", e)) } - ) + return retry(5) { + "$server/api/plays".httpGet(listOf(Pair("page", page))) + .set("Accept", "application/json") + .set("X-Secret", authenticationData.secret) + .set("X-Device-Id", authenticationData.deviceId) + .responseObject>().third + .fold( + { p: List -> + if (p.isEmpty()) { + null + } else { + page++ + Result.Success(p) + } + }, + { e: Throwable -> Result.Error(Exception("Error getting plays", e)) } + ) + } } return generateSequence { doFetch() } diff --git a/app/src/main/java/me/vanpetegem/accentor/api/track/Track.kt b/app/src/main/java/me/vanpetegem/accentor/api/track/Track.kt index f20e5da1..a4952575 100644 --- a/app/src/main/java/me/vanpetegem/accentor/api/track/Track.kt +++ b/app/src/main/java/me/vanpetegem/accentor/api/track/Track.kt @@ -1,6 +1,7 @@ package me.vanpetegem.accentor.api.track import com.github.kittinunf.fuel.httpGet +import me.vanpetegem.accentor.api.util.retry import me.vanpetegem.accentor.data.authentication.AuthenticationData import me.vanpetegem.accentor.data.tracks.ApiTrack import me.vanpetegem.accentor.util.Result @@ -10,22 +11,24 @@ fun index(server: String, authenticationData: AuthenticationData): Sequence>? { - return "$server/api/tracks".httpGet(listOf(Pair("page", page))) - .set("Accept", "application/json") - .set("X-Secret", authenticationData.secret) - .set("X-Device-Id", authenticationData.deviceId) - .responseObject>().third - .fold( - { a: List -> - if (a.isEmpty()) { - null - } else { - page++ - Result.Success(a) - } - }, - { e: Throwable -> Result.Error(Exception("Error getting tracks", e)) }, - ) + return retry(5) { + "$server/api/tracks".httpGet(listOf(Pair("page", page))) + .set("Accept", "application/json") + .set("X-Secret", authenticationData.secret) + .set("X-Device-Id", authenticationData.deviceId) + .responseObject>().third + .fold( + { a: List -> + if (a.isEmpty()) { + null + } else { + page++ + Result.Success(a) + } + }, + { e: Throwable -> Result.Error(Exception("Error getting tracks", e)) }, + ) + } } return generateSequence { doFetch() } diff --git a/app/src/main/java/me/vanpetegem/accentor/api/user/User.kt b/app/src/main/java/me/vanpetegem/accentor/api/user/User.kt index a7016ec6..4c63bd86 100644 --- a/app/src/main/java/me/vanpetegem/accentor/api/user/User.kt +++ b/app/src/main/java/me/vanpetegem/accentor/api/user/User.kt @@ -1,6 +1,7 @@ package me.vanpetegem.accentor.api.user import com.github.kittinunf.fuel.httpGet +import me.vanpetegem.accentor.api.util.retry import me.vanpetegem.accentor.data.authentication.AuthenticationData import me.vanpetegem.accentor.data.users.ApiUser import me.vanpetegem.accentor.util.Result @@ -10,22 +11,24 @@ fun index(server: String, authenticationData: AuthenticationData): Sequence>? { - return "$server/api/users".httpGet(listOf(Pair("page", page))) - .set("Accept", "application/json") - .set("X-Secret", authenticationData.secret) - .set("X-Device-Id", authenticationData.deviceId) - .responseObject>().third - .fold( - { u: List -> - if (u.isEmpty()) { - null - } else { - page++ - Result.Success(u) - } - }, - { e: Throwable -> Result.Error(Exception("Error getting users", e)) } - ) + return retry(5) { + "$server/api/users".httpGet(listOf(Pair("page", page))) + .set("Accept", "application/json") + .set("X-Secret", authenticationData.secret) + .set("X-Device-Id", authenticationData.deviceId) + .responseObject>().third + .fold( + { u: List -> + if (u.isEmpty()) { + null + } else { + page++ + Result.Success(u) + } + }, + { e: Throwable -> Result.Error(Exception("Error getting users", e)) } + ) + } } return generateSequence { doFetch() } diff --git a/app/src/main/java/me/vanpetegem/accentor/api/util/Util.kt b/app/src/main/java/me/vanpetegem/accentor/api/util/Util.kt new file mode 100644 index 00000000..0cfb57da --- /dev/null +++ b/app/src/main/java/me/vanpetegem/accentor/api/util/Util.kt @@ -0,0 +1,16 @@ +package me.vanpetegem.accentor.api.util + +import me.vanpetegem.accentor.util.Result + +fun retry(n: Int, block: () -> Result?): Result? { + var tries = 0 + var result: Result? + do { + if (tries > 0) { + Thread.sleep((2 shl tries) * 1000L) + } + result = block() + tries++ + } while (tries < n && result is Result.Error) + return result +}