retrofit icon indicating copy to clipboard operation
retrofit copied to clipboard

feature: SSE endpoints

Open MukjepScarlet opened this issue 4 months ago • 6 comments

Prototype (my demand):

@SSE
@GET("events")
suspend fun fetchEvents(): Flow<ServerSentEvent>

data class ServerSentEvent(
    val id: String?,
    val type: String?
    val data: String,
)

Pending:

  1. Should it be migrated into base module? (e.g. @SSE can replace @GET)
  2. What kind of result should be supported?
  3. Write in Kotlin or Java?
  4. Auto-reconnecting like JS? Or improve okhttp-sse module.
  5. How can we handle connection events like open/disconnected here?
  6. How to handle id, type, data for example Int? for id, enum for type and JSON data?

java.util.concurrent.Flow (Java 9+) / java.util.stream.Stream (Java 8+) might be the integrated ones... But Stream is not designed for tasks like this.

These questions need to be answered before actual works.


closes https://github.com/square/retrofit/issues/1029

MukjepScarlet avatar Aug 08 '25 08:08 MukjepScarlet

I think this can probably be entirely implemented in a call adapter with no changes to the core, but I'd have to try it.

JakeWharton avatar Aug 08 '25 18:08 JakeWharton

We might have more than one adapter for SSE (for example RxJava & Kotlinx coroutines), so the basic definition like ServerSentEvent (or ServerSentEvent<T>) probably need to be in the core module.

MukjepScarlet avatar Aug 08 '25 18:08 MukjepScarlet

Call adapters can delegate to each other. They do not need to be in the core.

JakeWharton avatar Aug 08 '25 19:08 JakeWharton

I planned to add a callback style for core module but it requires some improvements on okhttp-sse, another PR for that will be opened later.

MukjepScarlet avatar Aug 11 '25 14:08 MukjepScarlet

@JakeWharton Please review current work of this for further change/improvement/completion.

MukjepScarlet avatar Aug 12 '25 05:08 MukjepScarlet

Current usage:

@Streaming
@GET
fun ktxFlow(): Flow<ServerSentEvent<String, String, String>>

@Streaming
@GET
fun jucFlow(): Flow.Publisher<ServerSentEvent<String, String, String>>

@Streaming
@GET
fun callback(): EventSource<String, String, String>

The fields of ServerSentEvent will be converted as a String ResponseBody.

MukjepScarlet avatar Aug 12 '25 10:08 MukjepScarlet