Repository navigation
Expose HTTP Response headers from SqlResource - #13052
Conversation
177b179 to
3eee4ce
Compare
This change makes the SqlResource expose HTTP response headers in the same way that the QueryResource exposes them. Fundamentally, the change is to pipe the QueryResponse object all the way through to the Resource so that it can populate response headers. There is also some code cleanup around DI, as there was a superfluous FactoryFactory class muddying things up.
3eee4ce to
fe0fcfa
Compare
| if (sqlQuery.includeHeader()) { | ||
| responseBuilder.header(SQL_HEADER_RESPONSE_HEADER, SQL_HEADER_VALUE); | ||
| } | ||
|
|
There was a problem hiding this comment.
should this be always added or only in case where includeHeader() is true
There was a problem hiding this comment.
That's code that previously existed and I didn't change. It just looks like I changed it because of diff stuff. Look at lines 191-193 of the original.
|
Overall looks good, the Sequence has been changed to a QueryResponse with a separate class and removing the old static QueryResponse class. Most of the places which deal with sequences now has an additional getResult as the return type of execute is now a QueryResponse object. Have one minor comment so far |
clintropolis
left a comment
There was a problem hiding this comment.
seems like some legitimate failures
paul-rogers
left a comment
There was a problem hiding this comment.
@imply-cheddar, thanks for this improvement. A quick scan suggests the approach is sound. LGTM (non-binding)
Thanks for the cleanup of the SqlStatementFactory. I believe that awkward indirection was needed, in part, for some test hackery. If there is an issue, we'll fix it when it arises.
This change will conflict with an open PR to refactor the Calcite tests. However, I'll deal with that issue once this is committed.
Your approach to plumbing the QueryResponse up from the native engine parallels what I did in the "operator" branch for other reasons; the "operator" work can now build on your changes here.
| // following bindings are overriding other bindings that end up needing a lot more dependencies. | ||
| // We replace the bindings with something that returns null to make things more brittle in case they | ||
| // actually are used somewhere in the test. | ||
| binder.bind(SqlStatementFactory.class).annotatedWith(MSQ.class).toProvider(Providers.of(null)); |
There was a problem hiding this comment.
This only works if the MSQ tests never use the SQL layer (at least via Guice.) Our Calcite tests are currently a muddle because they hand-build a set of objects, maintained in static variables. An open PR starts to fix this with the ultimate goal of using Guice to create the objects so we don't have to entirely different systems to maintain.
In the branch where the Calcite test refactoring is happening, I ran into issues with the new MSQ tests: they do seem to use Guice, but with objects created in that static bundle of objects. Still trying to sort out that bit of confusion.
The question is then, do the MSQ tests use hand-created objects for the SQL layer or objects from Guice? This change suggests that they are hand-created and the Guice-provided ones are ignored (or we have multiple Guice injectors in play.)
Perhaps the best way to proceed is to commit this, then I'll rebase the Calcite test cleanup on this PR and see what's what.
There was a problem hiding this comment.
Yeah... when I was fixing up this test, it was definitely a bit of a mixed bag of strategies. What I saw is that some of the objects are coming from Guice, but some of the objects are being hand-created. I had to make this change because the place that I added the binding was used in the test, but the test also didn't have the other dependencies defined to make that "just work", so I had to give Guice just enough to let it make the injector
| * It seems extremely weird that the below code is wrapping the Sequence in order to emitLogsAndMetrics. | ||
| * The Sequence was returned by the call to execute, it would be worthwile to figure out why this wrapping | ||
| * cannot be moved into execute(). We leave this as an exercise for the future, however as this oddity | ||
| * was discovered while just trying to expose HTTP response headers |
There was a problem hiding this comment.
Native queries when running from SQL should probably not emit logs and metrics since there is code in the SQL layer to do that: assuming these are basically the same logs and metrics. Are we emitting SQL logs and metrics in SQL, but native ones here? Is that redundant? Should we figure this out?
There was a problem hiding this comment.
Which code in the SQL layer handles it? IIRC, the call on QueryLifecycle that this comment is on is special built only for the SQL code to use and I didn't see other code doing the logging, so I guessed that the code I commented on here is actually the only way that the SQL layer handles its logs and metrics.
We should figure it out, but not in this code change :). I already went sideways doing Guice stuff, don't want to go and expand scope even more ;).
| private final SqlToolbox lifecycleToolbox; | ||
|
|
||
| DirectStatement directStatement(SqlQueryPlus sqlRequest); | ||
| public SqlStatementFactory(SqlToolbox lifecycleToolbox) |
There was a problem hiding this comment.
Perhaps add a comment to point the reader to the SqlModule and SqlStatementFactoryModule to explain how these instances are created. It is, unfortunately, not intuitively obvious on the first read how things are now wired up.
There was a problem hiding this comment.
There is magic in DI platforms, to a certain degree, you must know the magic to know how things are wired up.
Generally speaking, there is one rule with using Guice that we should be following (I noticed that we have drifted from the rules in some of the code) to help know how things are wired up. Never, ever, ever, build on or expect implicit bindings (in the code I was looking at, I noticed a number of implicit bindings that were happening, I made explicit ones for everything that I found so far). We should always have an explicit binding in a module somewhere for everything that we expect to be bound. The reason for this is that without an explicit binding, it's impossible to do a usages search and figure out how things are setup. With an explicit binding, you can do a usages search on the class and then find the usages "as a .class" which tells you which Module it is bound in. Provider methods are kinda a gray area here and I generally try to keep away from them if possible. In this case, without revisiting the object structure in general, either a provider method or an actual provider would be required. For Provider methods, the .class usages don't show up, but if you also look for usages as a return value from a method, you can find the Provider methods as well. Additionally, usages of the constructor will show up here.
TBH, I would also just add the javadoc, but I'm scared of another multi-hour CI cycle blocking the PR. Maybe I'll do the javadoc and merge anyway.
| * at time of writing was not conducive to reuse in test code, so, instead of fixing that we just take the easy | ||
| * way out of adding the test-reusable code to this module and reuse that. | ||
| */ | ||
| public static class SqlStatementFactoryModule implements Module |
There was a problem hiding this comment.
Thanks for this. This is some fancy Guice wrangling that makes the setup a bit cleaner.
| final ServerConfig serverConfig | ||
| final ServerConfig serverConfig, | ||
| ResponseContextConfig responseContextConfig, | ||
| @Self DruidNode selfNode |
There was a problem hiding this comment.
Nit: add final to the above two items just to be consistent? I don't think the Java compiler cares: it can figure out that the items are essentially final. But, we seem to like including the statements as documentation.
|
I pushed up javadoc fixes and travis got into sad-land from flakey tests :(. Going to merge anyway, it was a clean build ahead of the javadoc push. |
* Expose HTTP Response headers from SqlResource This change makes the SqlResource expose HTTP response headers in the same way that the QueryResource exposes them. Fundamentally, the change is to pipe the QueryResponse object all the way through to the Resource so that it can populate response headers. There is also some code cleanup around DI, as there was a superfluous FactoryFactory class muddying things up.
This change makes the SqlResource expose HTTP response headers in the same way that the QueryResource exposes them.
Fundamentally, the change is to pipe the QueryResponse object all the way through to the Resource so that it can populate response headers. There is also some code cleanup around DI, as there was a superfluous FactoryFactory class muddying things up.
This PR has: