7
7
package at.bitfire.dav4jvm.exception
8
8
9
9
import at.bitfire.dav4jvm.HttpUtils
10
+ import at.bitfire.dav4jvm.exception.ServiceUnavailableException.Companion.DELAY_UNTIL_DEFAULT
11
+ import at.bitfire.dav4jvm.exception.ServiceUnavailableException.Companion.DELAY_UNTIL_MAX
12
+ import at.bitfire.dav4jvm.exception.ServiceUnavailableException.Companion.DELAY_UNTIL_MIN
10
13
import okhttp3.Response
11
14
import java.net.HttpURLConnection
12
15
import java.time.Instant
13
16
import java.util.logging.Level
14
17
import java.util.logging.Logger
15
18
16
- class ServiceUnavailableException : HttpException {
19
+ class ServiceUnavailableException : HttpException {
17
20
18
21
private val logger
19
22
get() = Logger .getLogger(javaClass.name)
20
23
21
- var retryAfter: Instant ? = null
24
+ val retryAfter: Instant ?
22
25
23
- constructor (message: String? ): super (HttpURLConnection .HTTP_UNAVAILABLE , message)
26
+ constructor (message: String? ) : super (HttpURLConnection .HTTP_UNAVAILABLE , message) {
27
+ retryAfter = null
28
+ }
24
29
25
- constructor (response: Response ): super (response) {
30
+ constructor (response: Response ) : super (response) {
26
31
// Retry-After = "Retry-After" ":" ( HTTP-date | delta-seconds )
27
32
// HTTP-date = rfc1123-date | rfc850-date | asctime-date
28
33
34
+ var retryAfterValue: Instant ? = null
29
35
response.header(" Retry-After" )?.let { after ->
30
- retryAfter = HttpUtils .parseDate(after) ? :
36
+ retryAfterValue = HttpUtils .parseDate(after) ? :
31
37
// not a HTTP-date, must be delta-seconds
32
38
try {
33
39
val seconds = after.toLong()
@@ -37,6 +43,41 @@ class ServiceUnavailableException: HttpException {
37
43
null
38
44
}
39
45
}
46
+
47
+ retryAfter = retryAfterValue
48
+ }
49
+
50
+
51
+ /* *
52
+ * Returns appropriate sync retry delay in seconds, considering the servers suggestion
53
+ * in [retryAfter] ([DELAY_UNTIL_DEFAULT] if no server suggestion).
54
+ *
55
+ * Takes current time into account to calculate intervals. Interval
56
+ * will be restricted to values between [DELAY_UNTIL_MIN] and [DELAY_UNTIL_MAX].
57
+ *
58
+ * @param start timestamp to calculate the delay from (default: now)
59
+ *
60
+ * @return until when to wait before sync can be retried
61
+ */
62
+ fun getDelayUntil (start : Instant = Instant .now()): Instant {
63
+ if (retryAfter == null )
64
+ return start.plusSeconds(DELAY_UNTIL_DEFAULT )
65
+
66
+ // take server suggestion, but restrict to plausible min/max values
67
+ return retryAfter.coerceIn(
68
+ minimumValue = start.plusSeconds(DELAY_UNTIL_MIN ),
69
+ maximumValue = start.plusSeconds(DELAY_UNTIL_MAX )
70
+ )
71
+ }
72
+
73
+
74
+ companion object {
75
+
76
+ // default values for getDelayUntil
77
+ const val DELAY_UNTIL_DEFAULT = 15 * 60L // 15 min
78
+ const val DELAY_UNTIL_MIN = 1 * 60L // 1 min
79
+ const val DELAY_UNTIL_MAX = 2 * 60 * 60L // 2 hours
80
+
40
81
}
41
82
42
- }
83
+ }
0 commit comments