-
Notifications
You must be signed in to change notification settings - Fork 9.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add timeout to SSE #8565
base: master
Are you sure you want to change the base?
Add timeout to SSE #8565
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,6 +16,8 @@ | |
package okhttp3.sse.internal | ||
|
||
import java.io.IOException | ||
import kotlin.time.Duration | ||
import kotlin.time.Duration.Companion.seconds | ||
import okhttp3.Call | ||
import okhttp3.Callback | ||
import okhttp3.Request | ||
|
@@ -24,6 +26,8 @@ import okhttp3.ResponseBody | |
import okhttp3.internal.stripBody | ||
import okhttp3.sse.EventSource | ||
import okhttp3.sse.EventSourceListener | ||
import okio.AsyncTimeout | ||
import okio.Timeout.Companion.timeout | ||
|
||
internal class RealEventSource( | ||
private val request: Request, | ||
|
@@ -40,6 +44,18 @@ internal class RealEventSource( | |
} | ||
} | ||
|
||
private fun updateTimeout(call: Call?, duration: Duration) { | ||
if (call?.timeout() is AsyncTimeout) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm a bit nervous about reusing
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What do you suggest then ? For the first point: currently (without the PR), we cancel this exact timeout (L69), so the point would be valid for the current state. |
||
(call.timeout() as AsyncTimeout).apply { | ||
if (this.timeoutNanos() > 0L) { | ||
exit() | ||
} | ||
timeout(duration) | ||
enter() | ||
} | ||
} | ||
} | ||
|
||
override fun onResponse( | ||
call: Call, | ||
response: Response, | ||
|
@@ -65,8 +81,11 @@ internal class RealEventSource( | |
return | ||
} | ||
|
||
// This is a long-lived response. Cancel full-call timeouts. | ||
call?.timeout()?.cancel() | ||
// This is a long-lived response. Cancel full-call timeouts if no timeout has been set | ||
listener.timeout?.let { | ||
// We spend at most timeout seconds if set | ||
updateTimeout(call, it.seconds) | ||
} ?: call?.timeout()?.cancel() | ||
|
||
// Replace the body with a stripped one so the callbacks can't see real data. | ||
val response = response.stripBody() | ||
|
@@ -76,6 +95,10 @@ internal class RealEventSource( | |
if (!canceled) { | ||
listener.onOpen(this, response) | ||
while (!canceled && reader.processNextEvent()) { | ||
listener.timeout?.let { | ||
// We spend at most timeout seconds if set | ||
updateTimeout(call, it.seconds) | ||
} | ||
} | ||
} | ||
} catch (e: Exception) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From Call, I think there is a convention on timeout names. Such as
readTimeoutMillis
. So perhapsreceiveTimeoutMillis
?I wonder if we should prefer Kotlin Duration here also?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
callTimeoutMillis
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Internally we use callTimeout in RealEventSource to track establishment, and it's obviously an existing top level think in OkHttp which extends to the end of a request.
read feel to I/O socket focused.