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
Blocking IO in content.writeString() [0.5.2-SNAPSHOT] #490
Comments
@jamesgorman2 apologies for the delayed response.
Yes in this case, RxNetty subscribes to the passed |
No worries @NiteshKant, saw you were on holiday recently and expected a bit of a delay. Good to hear you have a repro for this. (and thanks for all the work on RxNetty) |
Ok so an update to the issue. The problem here is of ordering of the items written. For HTTP, RxNetty adds a The reason for the wrong ordering of writes is as follows:
In this case, I have the fix for the issue but I am struggling to write a unit test that can deterministically reproduce this situation. |
Good work on spotting that. Sounds like your in maths-land with respect to proving correctness over non-deterministic parallel systems. Is the problem setting up a harness in the Netty layer rather than testing that the RxNetty layer is emitting in the correct sequence? |
The problem is to deterministically reproduce that race-condition which I describe 😄 |
Ordering issue happens when a write happens from a thread other than the eventloop. Reported issue was for HTTP, RxNetty adds a LastHttpContent at the end of the content stream to mark the end of chunked content. In this particular case, the LastHttpContent gets written before the content stream completes which causes the illegal state in the HTTP encoder. The reason for the wrong ordering of writes is as follows: Netty enqueues any writes that happen from outside the eventloop on to the eventloop task queue. It writes any write that happens from the eventloop, directly without enqueuing it to the task queue. In this case, request(n) calls to the content Observable happen on the eventloop, so if the producer(source Observable) is faster than the consumer (writes on channel) then request(n) may immediately produce an item which gets written on the channel as opposed to an item produced on the subscribeOn scheduler that gets enqueued to the task queue. This race results in messing up the order of the writes. In the worst case, if the order happens to be such that the LastHttpContent is written before the content stream completion, the HTTP response is malformed. The fix is to not have write happening on the eventloop, happen before the writes from outside the eventloop. Thus, if there is any write happening from an `Observable` outside the eventloop. Writes on the eventloop also will be enqueued in the queue. This preserves the ordering.
Hi there,
we have code returning the results of a JDBC call (blocking IO) in a
reponse.writeString()
. Trying to offload this toSchedulers.io()
results in an intermittent failure:code (when unwound):
NB - I've include the
onErrorResumeNext
in this order since it's part of how our composition goes togetherWhen we hit the service in AWS with ~7 concurrent requests we'll get 1-2 failures with the response truncated part way through the result sets (ie it is sending some data that has been returned from the database).
If will repro more intermittently from curl on my dev host.
observableOfJdbcResultsAsAString
is a composite Observable, and I can produce the same error consistently by adding.subscribeOn(Schedulers.io())
to an inner Observable.A couple of questions:
nio-eventloop
if I have too many long running queries?subscribeOn
correctly here? any idea on where to look to understand the intermittent failure** I am currently assuming (Rx)Netty doesn't like me thread switching during the
writeString
but I don't think I'm doing it herecheers,
James
The text was updated successfully, but these errors were encountered: