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
QueueSource should complete future returned by .offer()
only when element is sent to downstream
#26696
Comments
I'm not sure, sounds dangerous to change semantics just to fit your use case, there is very likely existing user code relying on the current behavior. I have seen people struggle with this before though, so maybe an imperative N-producer source would be useful (and better documenting that Source.queue is tricky for that use case). BTW, that sample isn't thread safe, you can't safely mutate shared global state like that hashset from inside streams or Futures and be sure the changes are visible from other threads. |
I agree that is the desired semantics
I think that is the correct behaviour
I don't think so: it only throws when
Perhaps the documentation is slightly misleading there, but the logic looks correct to me so far. I hope to review your reproducer later.
Even if there is a bug in the logic here, I think we should only fix the bug, and not change the semantics as you propose: if we'd complete the promise after sending the buffered item downstream, and the user is only allowed to offer a new element when the future is resolved, then the buffer would always be empty, right? |
Looking closer at the reproducer,
I think this works as designed: the exception is caused by the fact that you broke the contract of waiting for the Does that make sense? |
That's why I mentioned that an imperative N-producer operator could perhaps make sense. |
I must admit I didn't quite understand what you meant by that :D. Would that be a queue-like source that allows for up to |
Isn't a workaround for that use case to use one queue per writer and merge those afterwards? It seems the current confusion also comes from the fact that the queue interface and semantics are quite overloaded by being able to specify OverflowStrategies. The queue interface is safe to use concurrently but as observed here it only makes sense if the strategy is not |
Yeah, I didn't go so far to think of a solution, more the problem that is reported over and over when users try to use |
#28272 was implemented for release in Akka 2.6.5 and allows pushing from several threads. |
Hi guys!
I believe current implementation of
QueueSource
in backpressure mode makes it unusable and violates what's described in documentation.To quote, it says:
This statement, in my understanding, implies I can rely on
QueueOfferResult
to know when to offer next item. Currently it completes promise as soon as item is put toQueueSource.buffer
. It means if call toQueueSource.offer()
fails withIllegalStateException("You have to wait for previous offer to be resolved to send another request")
I can't rely on previously returned futures to know when to call.offer
again. In fact I'll have to implement my own buffer aroundSource.queue
and I tried hard and discussed it few times in your Gitter :)I believe right thing to do is to complete promise AFTER buffered item is sent downstream.
To reproduce the problem call
.offer
in more threads than (buffer size + 1) (I'll talk about plus-one later).In current (2.5.22) version it fails instantly where client developer expects
QueueSource
to respect buffer limitation and not to complete offer futures until items are really gone. So it quickly fills up buffer andQueueSource.pendingOffer
.I have pull-request that fixes this but it breaks few tests, particularily
that built around faulty logic. I can fix the test but there is risk that some clients may be imlemented around such behavior. On the other hand with proposed fix their code should not fail. It's just going to be correctly backpressured.
I think fixing this will also address #25798
With proposed fix promises of dropped items will never be completed in DropHead/DropTail/DropBuffer/Fail modes. I'm not sure if I should create separate ticket for this but I believe it should be fixed too. Please advise (@jrudolph).
Finally I don't understand purpose of
QueueSource.pendingOffer
. It acts as one-item-buffer which again is misleading from what documentation says thatmaxBuffer
parameter defined number of buffed items. In reality number of buffered items is (maxBuffer + 1). Perhaps original author first implementedQueueSource
without buffer, only withpendingOffer
, and later added backpressure mode. Test"fail offer future if user does not wait in backpressure mode"
accounts for this though. I believependingOffer
should be dropped in favor ofQueueSource.buffer
if this PR is accepted. So far it looks likeQueueSource.pendingOffer
is used to wait on (from client code) when we have only one producer calling.offer
.The text was updated successfully, but these errors were encountered: