-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Merge different Resource implementation classes #7732
Conversation
1bbdbf2
to
f5b7968
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so... I've got one of my annoying opinions: as discussed briefly in #synapse-dev, your _AsyncResource
feels like it is mixing separate concerns, and additionally it feels like the DirectServeResources are just doing a subset of what JsonResource needs to do anyway. (I've always felt like this: DirectServeResource
should have been AsyncResource
to my mind.
My (current) suggestion for a class heirarchy:
Resource
^
|
AsyncResource
^ ^ ^
+---/ | \------+
AsyncHtmlResource | AsyncJsonResource
| ^
CallbackResource |
^ |
| +---/
JsonServletResource
AsyncResource
overrides render
to look for async_render
, async_render_GET
, etc; it also has stub functions for _handle_error
(drops the connection and logs by default?) and _handle_result
(to handle a non-empty result from async_render_*
: probably does nothing default, but might even raise a not-implemented exception?)
{Json,Html}Resource
can provide implementations of _handle_error
and _handle_result
which return something to the client, taking the place of DirectServe{Json,Html}Resource
.
CallbackResource
has an async_render
which does the stuff you currently have inside the try block of _AsyncResource
(https://github.com/matrix-org/synapse/pull/7732/files#diff-c2761a2c74c6c134fb39216aef055306R229-R256).
JsonServletResource
is a renaming of the current JsonResource
.
(It's unclear if we need both CallbackResource and JsonServletResource: perhaps we can combine them back into a single class, thus avoiding the multiple inheritance?)
I think you can also hook whatever it is trace_servlet
is supposed to be doing at AsyncResource
? Though I must admit I've failed to grok the bug you're trying to fix here.
I think that's basically what we have today, modulo abusing the I guess ideally all I want is to separate the routing from the rendering, although this PR gets a bit unstuck trying to support HTML vs JSON. One possible way of doing this is to have an Now, the problem with that is the error handling, as now
TLDR: the current code ends up effectively calling |
There's a bunch of stuff that
I call that at least six lines :)
I'm not sure I love this plan. |
It's also annoying boilerplatey boilerplate, to get all the exception handling right. |
I am a bit confused how your classes are different than mine, in terms of avoiding mixing of concerns. Each layer seems to be doing pretty much the same things, just implementing things a bit differently (or having I think having the render function call out to a function that subclasses implement to handle the request is nicer than it calling a function to get the callback is a nicer way of doing things. (Though its worth noting that doing it like that means we call I don't really understand why we would implement stub functions for
I think we can make that work either way TBH.
Fair, it was an attempt to try and separate out the concerns between rendering and routing more explicitly. |
This sentence doesn't make any sense, which is a shame because on closer inspection I think it's basically the nub of the difference between our approaches. In my approach, rather than having
trace_servlet doesn't need to be implemented as a wrapper... you could do what it's doing inline instead.
fair, scratch that part of the plan; keep them as abstract functions. |
Incidentally, I think this would be better solved by using the resource tree as it is intended (ie, having individual |
I think it would be helpful if you could answer what you're objections are to the current approach that you're trying to fix. I do think that your |
Two things, basically:
|
Ok, thanks. I guess I just see it all as routing, but am happy to rejig. |
The problem with the new approach is that now we need to move the I suppose the correct, ish, way of fixing this is to have each servlet be a Thoughts on how to get out of this welcome, though at this point I might just give up on the idea of de-duplicating the code and just fix the specific case of opentracing and move on |
oh, balls.
|
(otherwise yes, that is a major flaw in my plan, and it's up to you whether you stick with your proposal or patch the current situation up) |
Aha, actually looks like we can change the operation name, which isn't possible using the standard opentracing APIs but is possible in the jaeger specific APIs. In which case we can actually just set the operation name based on the request name at the end of the rendering, rather than duplicating that logic. (What you can and can't change is quite arbitrary....) |
to confirm: this won't confuse nested spans that have come and gone by the time we finish rendering? |
I don't believe so, as they all use opaque IDs internally. Will test on jki.re though. |
23399f3
to
40b84a0
Compare
Ok, I've rejigged everything as discussed. Sorry that it's all in a single commit |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm much happier with this now; thanks!
have you checked that OPTIONS works everywhere we could conceivably have broken it?
with scope: | ||
result = func(request, *args, **kwargs) | ||
if opentracing is None: | ||
yield |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
kinda wondering about the overhead here. There's a _NullContextManager
in generic_worker.py
which we could pull out and use...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A single if statement per request doesn't fill me with terror, if I'm honest.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's not the if statement I'm worrying about, but more the infrastructure involved in instantiating a generator, constructing a GeneratorContextManager to wrap it, and then doing the callbacks.
I'm inclined to agree it's not worth lying awake at night over though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah right I see, I forgot that we'd need to generate a context manager object each time
af3a628
to
f0f2baf
Compare
Most of the |
@erikjohnston Looks like I bitrotted this. There are conflicts now! 😢 |
with scope: | ||
result = func(request, *args, **kwargs) | ||
if opentracing is None: | ||
yield |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's not the if statement I'm worrying about, but more the infrastructure involved in instantiating a generator, constructing a GeneratorContextManager to wrap it, and then doing the callbacks.
I'm inclined to agree it's not worth lying awake at night over though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
couple of minor things, generally lgtm
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🚢
* commit '5cdca53aa': Merge different Resource implementation classes (#7732) Fix inconsistent handling of upper and lower cases of email addresses. (#7021) Allow YAML config file to contain None (#7779) Fix a typo. Move 1.15.2 after 1.16.0rc2. 1.16.0rc2 Remove an extraneous space. Add links to the fixes. Fix tense in the release notes. Hack to add push priority to push notifications (#7765) Add early returns to `_check_for_soft_fail` (#7769) Use symbolic names for replication stream names (#7768) Type checking for `FederationHandler` (#7770) Fix new metric where we used ms instead of seconds (#7771) Fix incorrect error message when database CTYPE was set incorrectly. (#7760) Pin link in CHANGES.md Fixes to CHANGES.md
We currently have two
Resource
classes that work in slightly different ways, this is an attempt to de-duplicate some of the code and make things more consistent (ironically by adding more classes).Concretely, this fixes a bug where
trace_servlet
would trigger a"Tried to close a non-active scope!"
error each time a request was processed inDirectServeResource
if opentracing is enabled. This is because thetrace_servlet
wrapper was added after thewrap_async_request_handler
, which meant that logcontexts would be forcibly dropped before the handling intrace_servlet
happened. This is handled correctly byJsonResource
, so by refactoring things so that they share the same code we can fix that bug.