-
Notifications
You must be signed in to change notification settings - Fork 132
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
Nested queries get stuck when using transactions (bound single connection) #194
Comments
Can you provide more details? Do you use connection pooling and do you have a If so, then a couple of things play into that. First, the database connection is pinned to the Secondly, the code calls operations on a connection while the connection hasn't consumed all results from the previous query. Rows are emitted as data is received and decoded from the transport channel. That means, the mapping function at In the next step, the code tries to issue sub-queries on the same connection. What happens now is that queries are sent to the connection but sub-queries do not receive any data because the outer query isn't completed. Therefore, inner subscribers are left with the initial demand and lock up the connection. |
Indeed, Thank you for the explanation on what happen internally. Could you suggest a way to get this working ? I'm not yet that familiar with (spring-data-)r2dbc and trying to learn |
I just tried the same code with a A first one is used by the So it should work but I have the exact same behavior as before so I've to admit that I'm a bit lost. |
Also, I added a .onBackpressureDrop(new Consumer<Broadcast>() {
@Override
public void accept(Broadcast broadcast) {
System.out.println("DROP");
}
})
.doOnRequest(r -> System.out.println("RQ 1 " + r)) right after the |
Avoid stream creation while another stream is active (Famous quote: Do not cross the streams) as general rule. If you want to fetch related data, then ideally collect all results as Something like the following snippet should do the job:
|
I'll continue on SO then: https://stackoverflow.com/questions/58094931/spring-data-r2dbc-backpressure-not-taken-into-account Mainly: my issue regarding your suggestion is that we need to keep all in memory before starting to process the data while I kinda like the "stream" approach that doesn't requires me to store millions of lines in memory. |
Moving to Stack Overflow is a good idea to share our discussion with the community.
Yes, that is the case. In imperative programming, we typically consume data as I'm going to close this issue as we have now a SO post. |
@mp911de I know the the SO thread should centralize this discussion but since no replies are coming and even if testing a lot of stuff, I can't manage to get this working without saving everything in memory. Regarding
I do not agree, or not in this case to be more precise. I personally think that the notion of Flux / Stream / pipeline / ... is exactly this: stream process a set of "events", transform them, enrich them, ... and finally, in the last subscriber, save them / print them / ... whatever. My requirement is also quite simple, I'm trying to implement some sort of "lazy loading" of a child entity and this looks like a good use-case for stream processing (read a stream of source entities, enrich them, then write them to an output stream). After your suggestion regarding transaction management, I did a lot of tests using a non-transactional database client but can not figure out why this doesn't work... My observation is that (I use r2dbc-pool, and a flatMap with a concurrency limited to 2) a first connection is used for the initial find, while two others are used for the flatMap enrichment operations... and this works for about the 80 firsts root entites before blocking everything. Given the fact that this works for some time, I think the overall logic is good (we use it with many other technologies such as couchbase and Cassandra) but there is probably something wrong in the connection reset or such a thing. What are your thought on this ? |
You need to take into account, on which connection you run queries. In the transactional context, you're operating on a single connection that maps to the I/O stream of database wire protocol frames. When SQL query results are not fully consumed from the connection before you issue further commands, then a lockup is almost guaranteed. So
Should probably become:
From a high-level perspective, here's what happens:
Let me know if that outline makes sense. |
This perfectly makes sense in a transactional context since a single connection is used, but what I don't get even when thinking hard about it is why this happens even without the transactional client, which means on other connections... I'll do some tests using the 1.0 RC1 release |
Can you provide a reproducer? Without transactions, that issue should be gone. Not sure whether this is a driver of a Spring Data R2DBC issue, but we'll figure it out. |
Well... you know what ? Using the last version (1.0 RC1) I got it working fine in a non-transactional context... and the expected blocking behavior in a transactional one. Unless you think investigating this on a old version is meaningful, I'll just stick with the last r2dbc + spring-data-r2dbc versions :) |
Thanks a lot for checking. Then let's close this ticket here. I'm going to change the title to reflect the transactional behavior so future users can find that issue easier. |
@cambierr Hi, have u found any solution? |
Hi @Lexas228, I went for the simplest solution, that is basically to process my dataset by match of 10k rows... that is load 10k, buffer them, process them, again. This is slightly against the "streaming" approach of reactor but this does the trick :-) |
Hi,
I just tried a very simple Exemple, based on two reactive repositories:
Given
br
, a r2dbc crud repo, andcr
, another r2dbc crud repo:This code samples never completes (only the 250 first, or so, entries reach the
.collectList
operator). After some digging, adding someonBackpressureXXX
operator after thefindAll
seems to "fix" the issue by... well, dropping elements or buffering them.At this point, my understanding is that the r2dbc reactive repositories doesn't uses the consumer feedback mechanism which removes a significant part of r2dbc's benefits.
Am I wrong ? Is there any better way to achieve the same objective ?
Thanks !
The text was updated successfully, but these errors were encountered: