quarkus: Server Sent Events delaying 200 response

Describe the bug

I am on 2.6.1.Final. I have an endpoint that is an SSE endpoint. The status code is only returned after the first element is produced.

This was not the case in 1.x and can lead to timeouts on clients.

Expected behavior

I would expect a 200 to be returned immediately (provided everything worked as expected).

Actual behavior

The status code, headers, etc. is not returned until the moment the first item is produced.

How to Reproduce?

getting-started.zip

Output of uname -a or ver

Linux jose-buguroo 5.11.0-41-generic #45-Ubuntu SMP Fri Nov 5 11:37:01 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux

Output of java -version

openjdk version “14.0.2” 2020-07-14 OpenJDK Runtime Environment (build 14.0.2+12-46) OpenJDK 64-Bit Server VM (build 14.0.2+12-46, mixed mode, sharing)

GraalVM version (if different from Java)

No response

Quarkus version or git rev

2.6.1.Final

Build tool (ie. output of mvnw --version or gradlew --version)

Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f) Maven home: /home/jose/.m2/wrapper/dists/apache-maven-3.6.3-bin/1iopthnavndlasol9gbrbg6bf2/apache-maven-3.6.3 Java version: 14.0.2, vendor: Oracle Corporation, runtime: /home/jose/.sdkman/candidates/java/14.0.2-open Default locale: en_US, platform encoding: UTF-8 OS name: “linux”, version: “5.11.0-41-generic”, arch: “amd64”, family: “unix”

Additional information

From what I see SseUtil.send is producing the response the first time an element is produced. Therefore, until the first element is generated, no call to it happens and no response is flushed. I see this could have to do with PublisherResponseHandler suspending the context. I wonder if an option could be to have that class handle SSE slightly different and generate a status code.

I see that adding:

requestContext.serverResponse().setStatusCode(200)
requestContext.serverResponse().setChunked(true)
requestContext.serverResponse().write(new byte[]{})

to PublisherResponseHandler works as expected (i.e. we get the status code, headers, etc. and then the events get produced as they come). Any reason you can think of not to do that?

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 2
  • Comments: 29 (28 by maintainers)

Commits related to this issue

Most upvoted comments

I’m no SSE expert, just a user, but as a user I would expect the 200 to come right away and then receive the events.

Maybe @cescoffier has an opinion too as he played quite a lot with this.

I’m only ever referring to RestEasy server here. By “client” in the above quote I meant an EventSource as defined by the WHATWG Spec.

I agree that the status should be sent ASAP and we shouldn’t be waiting for a first message.

@cescoffier It seems we could easily find a middle ground here. I would think that any resource method that has returned a Multi or Flow or equivalently setup JAX-RS’s asynchronous & SSE systems should be considered a 200 OK. This allows the resource method to prepare things, and possibly throw an exception for 400, 401, etc. In all other cases a 200 should be assumed and sent.

Basically by the time control returns back to RestEasy, the resource had their chance to set things up and possible report errors, if not it should be a successful “setup”.

WRT to the 204, what is the use? SSE is designed for long lived connections that are expecting streams of events. What would be the harm in sending a “200”, then not sending any events and finally closing the connection. IMHO, as an SSE client, this is what I would expect not a 204; that seems like some kind of premature optimization that is wholly unnecessary.