Skip to content

Fix case where streaming can become disabled #2332

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

Merged
merged 4 commits into from
Nov 12, 2019

Conversation

taer
Copy link
Contributor

@taer taer commented Sep 25, 2019

Fix for #2331

Signed-off-by: Robert Macaulay <robert.macaulay@gmail.com>
val config = parse(yaml)

val streaming = config.routerParams(Stack.Params.empty)[Streaming]
assert(streaming.disabled)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not think this will be disabled

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup.. I had it right. Then formatted and changed the conditions to clean it up.. And just got lost in the code. :)

Updated PR

val config = parse(yaml)

val streaming = config.routerParams(Stack.Params.empty)[Streaming]
assert(streaming.enabled)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, according to your logic, this will not disable streaming as it will hit the (_, Some(streamAfter)) case

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

stupid brain fart commit. Fixed.

Copy link
Member

@zaharidichev zaharidichev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very good catch. Now that I think about it, I wonder whether there is even point of having the streamEnabled config. What if we just leave streamAfterContentLengthKB and rely on that to enable streaming for messages that are above this threshold ? What do you think @taer

@taer
Copy link
Contributor Author

taer commented Sep 26, 2019

I can't imagine anyone would want to disable streaming ever. But from what I can tell, disabling streaming forces a total buffer and a Content-length. The streamAfter I think seems to tell linkerd to convert Content-Length into chunked? I honestly don't 100% understand what that does. But if someone were to want to Content-Length everything, then you'd have to keep that streamEnable option. And you don't want to prevent someone who relied on that from upgrading.

They are dependent on each other.

You could have contentLengthEncodeAll: true -- but that's just the inverse.
You can't really convert chunkToContentLength based on a size, so no parameter makes sense there.
I assume streamAfterContentLengthKB means if CL is > X, then change the entire thing to chunked encoding response.

I think you're stuck w/ a boolean and the now optional steamAfter setting. We could fail startup for the illegal cases

Did I get the streamAfterContentLengthKB concept correct?

Swapped the assertions when I was organizing the file

Signed-off-by: Robert Macaulay <robert.macaulay@gmail.com>
val config = parse(yaml)

val streaming = config.routerParams(Stack.Params.empty)[Streaming]
assert(streaming.enabled)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@zaharidichev Any ideas on how to test the payload here?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunatelly finagle has that private, so I dont see a way of accessing it. Quite a pity indeed.

@zaharidichev
Copy link
Member

@taer
To get some more additonal context on things. I made an attempt at explaining some of the differences around chunked, streaming, etc right here. Hope this is useful.

I assume streamAfterContentLengthKB means if CL is > X, then change the entire thing to chunked encoding response.

I beleive you are right here.

The real question now is whether we should actually check for the illigal case. Can we really have streaming disabled and streamAfterContentLengthKB. And by the looks of it, the answer is no, because if you look at the finagle params you cna quickly see that when streaming is disabled, we are setting it to disabled and having streamAfterContentLengthKB does not play any role. So I would say, if you go ahead and add a check to fail the config initialization when this logical conflict arises, that will be great.

@taer
Copy link
Contributor Author

taer commented Oct 3, 2019

Should we just throw an exception with the message in it? Or does linkerd have a more fanciful way to handle this?

@zaharidichev
Copy link
Member

@taer
I think you can resort to using the config package and do some validation there. You can also throw
a ConfigError. You an take a look at how these are used around the codebase.

@zaharidichev
Copy link
Member

zaharidichev commented Oct 15, 2019

@taer Are you still keen on moving that forward, or I should just take it from here?

@taer
Copy link
Contributor Author

taer commented Oct 15, 2019

@zaharidichev Heya. Sorry about the delay. Had "normal" job things to work on. I'll do the simple throwing of the configException real quick and push that up

Signed-off-by: Robert Macaulay <rmacaulay@homeaway.com>
Copy link
Member

@zaharidichev zaharidichev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work, just some minor nits :)

Comment on lines 118 to 124
try {
parse(yaml)
fail()
} catch {
case _: InvalidDefinitionException => //Expected
case e: Throwable => fail(e)
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can rewrite this in a more compressed manner:

    intercept[InvalidDefinitionException] {
      parse(yaml)
    }

case (Some(true), None) => hparam.Streaming(5.kilobytes)
case (None, None) => hparam.Streaming(5.kilobytes)
case (Some(false), None) => hparam.Streaming(false)
case (Some(false), Some(_)) => throw ConflictingStreamingOptions(_label.getOrElse("unknown")) //tried label property, but it NPE's in test
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you are talking about HttpConfigTest, it does not NPE for me if use the def label

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Strange. It did once. Now it's happy.

Comment on lines 3 to 13
import com.fasterxml.jackson.databind.exc.InvalidDefinitionException
import com.twitter.conversions.StorageUnitOps._
import com.twitter.finagle.buoyant.Dst
import com.twitter.finagle.http.param.{FixedLengthStreamedAfter, Streaming}
import com.twitter.finagle.http.{Method, Request}
import com.twitter.finagle.{Dtab, Path, Stack}
import com.twitter.util.Future
import io.buoyant.config.Parser
import io.buoyant.config.{ConflictingStreamingOptions, Parser}
import io.buoyant.linkerd.{IdentifierInitializer, RouterConfig}
import io.buoyant.linkerd.protocol.{HttpConfig, HttpIdentifierConfig, HttpInitializer}
import io.buoyant.router.Http
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The com.twitter.conversions.StorageUnitOps._, FixedLengthStreamedAfter and ConflictingStreamingOptions seem to be unused, can we just remove them ?

Signed-off-by: Robert Macaulay <rmacaulay@homeaway.com>
Copy link
Member

@zaharidichev zaharidichev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot for helping with that @taer! Nice work!

@@ -17,6 +17,9 @@ case class ConflictingSubtypes(t0: NamedType, t1: NamedType) extends ConfigError
case class ConflictingLabels(name: String) extends ConfigError {
def message = s"Multiple routers with the label $name"
}
case class ConflictingStreamingOptions(name: String) extends ConfigError {
def message = s"Conflicting streaming options set. Can't disable streaming and set streamAfterContentLengthKB in $name"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason this cannot be a simple val?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just cloned ConflictingLabels error.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants