-
Notifications
You must be signed in to change notification settings - Fork 596
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
formFields and Error in stage [unknown-operation]: Promise already completed #73
Comments
Thanks for reporting, looks weird indeed. |
@ktoso, yes, 2.4.2. I indeed use something weird for requests - AWS Ruby SDK (I'm trying to emulate SNS) or curl+Charles proxy. When I use curl directly it always works:
when I use the same curl command via Charles (another port) sometimes it doesn't work. In Charles it looks like this (same requests): Also fails in Travis: https://travis-ci.org/s12v/sns/builds/114896929 (log.txt in the end) |
I'm in the process of porting a spray application to akka-http (2.4.2) and I'm seeing the same exception intermittently across multiple routes handling POST requests. As with s12v I don't see it when I'm making requests against the application directly, in my case it occurs when the application is placed behind an AWS Elastic Load Balancer. The stack trace is the same though I'm also seeing when using the The only other thing I've noticed is that the incidence rate increases with the number of requests being concurrently handled by the application, peaking at about one every three requests when I'm flooding the application with test requests. edit: It seems like the defaultEntity is getting set by the parser in the error cases. Is content length being mangled by AWS? |
The entity source has actually been completed successfully but is then materialized again for some reason, the actual exception happening when the promise is already completed is: |
Already reported before as #19506 |
And #18591 |
What happens, as far as I have understood it, is that the form fields will not share a single unmarshalling of the entity into a |
Also running in to this issue, but on the client-side when there are multiple reads of the response entity. One simple way to reproduce the
It isn't clear to me whether we are allowed to re-use |
AFAICS the route you posted should be totally fine @mpilquist – you only consume the databytes once, for writing the response back as I see this. |
@ktoso In the reproduction case I created using the echo route on the server, my client side was:
In a production app where I've experienced this issue, it occurs when a chunked response entity is both unmarshalled and logged using a custom response logger. |
No, it's not reusable. Would make sense to document that more explicitly. |
IIRC there may have been a conscious decision to support formFields properly only for strict entities (maybe because it's quite hard to fix it properly, see below). On the other hand, the current solution seems to be quite undecided in what it wants to support (full support for Strict entities, support for a single formField directive with a single field for streamed ones, no clues whether streamed entities should be supported and also no tests for the streamed case). Forbid formField for non-strict entities?So, general answer could be not allowing
In practice, this restriction might be hard to fulfill if you want some branches to deal with the entity in a streaming fashion). Also, it contradicts the philosophy of the routing DSL of being flexible and composable without giving you too many constraints. It would be better if the current behavior could be fixed. Approaches to fixing the problemFor the streamed case there probably exist several problems (I inferred that from the reported issues and the code, not from actual testing):
I think the cause of issue A) is that Case B) is already harder as it requires that the formField directive passes down the strict entity data (or StrictForm) data to the inner routes. The simplest solution would be running Case C) is much harder to fix. In that case the strict entity produced in one branch of the routing tree would have to be transported to a sibling alternative branch if the first branch rejects the request after having drained the request entity. But, alas, this is not possible because sibling branches in the routing tree cannot exchange information (but through rejections). This case identifies a problem with the routing DSL in Akka HTTP where the request is not immutable any more (compared to spray). The routing DSL assumes that the request object is immutable and fully reusable in the route alternative operator Possible solutions could be:
These solutions share an ugly secret: routing a request through one branch of the routing tree may have the side-effect of slurping in the whole request entity, at least if the content-type is |
Thanks for the in-depth analysis @jrudolph! Getting more mutability into the entity while ugly may indeed be something we'll want to do for a number of reasons actually – one of them being auto-draining (akka/akka#18716), so perhaps good to consider if a special source in there would be able to solve help us address both issues... No single of the solutions seems like "the right way to go", so we'll need to figure out the trade offs. I'll try to sleep on it and revisit soon again hm. Related: Also related to formFields was the issue here akka/akka#19042 (comment) in which we attempted to implement |
For AWS ELB one can workaround by using TCP ELB instead of HTTP ELB
I tested it and see no issues anymore |
Unfortunately switching to TCP ELB does not help. Certain big POST requests still fail, and 100% reproducible. If I go via nginx (rather ELB), requests work fine. |
Workaround: put service behind nginx which would response with HTTP 100 on behalf of the service. |
FWIW, I'm having same issue as @compositor. Behind ELB I get the error regularly, but not hitting the service directly. |
@jrudolph, could you please give an example, how to do it? I've also tried |
Hmm, I tried val toStrict = mapInnerRoute { innerRoute =>
extractRequest { req =>
onSuccess(req.toStrict(1.second)) { strictReq =>
mapRequest(_ => strictReq) {
innerRoute
}
}
}
}
// Workaround for https://github.com/akka/akka/issues/19981
val safePost = mapInnerRoute { innerRoute =>
post {
toStrict {
innerRoute
}
}
} but that didn't help me either.... |
OK, my error, I'm now applying the |
Hello. I have also been affected by this issue. I Could reproduce this issue 100% of the times through R package "httr" to submit POST request of two form fields. Using the toStrict solution solves the issue. Is there any insights on a permanent solution? can this be solved? what does the current workaround imply? I am using Akka 2.4.6 and scala 2.11 |
@saifellafi Reproducing this bug is not a problem, fixing it however is far from trivial. Using |
Hello, any follow up on this one? |
My comment above is still accurate. Some time ago I started working on the ii.) solution above which isn't trivial to get right. I hope to get to it at some point. When that is done, we should also simplify the current |
Thanks to #2283, at least the non-nested variant with multiple fields ( |
With #2524 I think both scenario 'A' and 'B' should now be covered. |
Wednesday Mar 09, 2016 at 12:22 GMT
Originally opened as akka/akka#19981
I'm having intermittent exception when using akka-http and
formFields
:It's one of 10 or 100 requests, pretty random, other requests are fine.
This is the code (I think only
handler
is relevant):If I remove
formFields
(and have onlypathSingleSlash {complete(r)}
) the issue is gone.What can be a reason, am I doing something wrong? A bug?
The text was updated successfully, but these errors were encountered: