Conversation
|
It seems like usually Do we want to do the same here or relying on the git history to find this info looks good enough ? EDIT: I am planning to not squash this PR to keep the rationales around in the commit messages. |
|
I think a few of these are functions which are decorated by In general it seems like this has a fairly high false positive rate, which is sad to see. |
It looks like the git history just says "ignore these" -- I think squashing those all together would be fine. I suspect it would be better to include the reasoning in comments in the code or add comments to |
3f982e3 to
04c726d
Compare
Indeed not sure why I didn't noticed. So no bugs, I'll include them in the relevant commit.
I should add more details in the commit messages to explain the rationale of each type of changes.
That makes complete sense for For e39d757 it's however a bit more annoying since it is the same rationale but in quite a number of different places. |
04c726d to
53ca28a
Compare
|
@MatMaul Is this worth following-up with or should we close it? |
Per #14947 (comment), my vote is for landing this. |
|
I've merged in develop and will fixup what I can. |
DMRobertson
left a comment
There was a problem hiding this comment.
I think this looks good, but I did do some of this myself---so would like another set of eyes.
AFAICS there are three categories of warnings we're suppressing here:
run_in_backgroundandrun_as_background_processreturn deferreds so you can block until---or do something after---the background task completes.- we call a method on a Deferred which returns
self, and mypy complains that the return value is unused - synchronous ops that return a Deferred (e.g. popping from a
Dict[str, Deferred])
The first class causes a lot of noise here. I wonder if we should make run_in_background and run_as_background_process return None---I don't think we ever use their return values. (And if we did we could have two variants, e.g. run_in_background_and_discard versus run_in_background_and_ which does return a deferred, say run_in_background_returning_handler` or something.)
| defer.ensureDeferred( # type: ignore[unused-awaitable] | ||
| run_as_background_process("background_updates", run_background_updates) | ||
| ) |
There was a problem hiding this comment.
Is the call to ensureDeferred actually doing anything here? run_as_background_process returns a Deferred and ensureDeferred is a no-op when its argument is a Deferred.
(I also find this script really confusing---the way it starts the reactor and gets the task being run to stop the reactor!)
There was a problem hiding this comment.
I suspect that we can remove the ensureDeferred call.
|
|
||
| gc_task = task.LoopingCall(_maybe_gc) | ||
| gc_task.start(0.1) | ||
| gc_task.start(0.1) # type: ignore[unused-awaitable] |
There was a problem hiding this comment.
This returns a deferred which fires when the gc_task.stop() is called---which it never is---or if the task fails. Seems safe to ignore.
| # `new_defer.callback()` call above. | ||
| if self.key_to_current_writer.get(key) == new_defer: | ||
| self.key_to_current_writer.pop(key) | ||
| self.key_to_current_writer.pop(key) # type: ignore[unused-awaitable] |
There was a problem hiding this comment.
Not sure what is going on here. I think this is safe?
Thoughts:
- I wonder if
del self.key_to_current_writer.pop[key]would work here? - Is it possible for
self.key_to_current_writer.get(key)to change between line 637 and 638? (I don't think so---there shouldn't be another thread accessing this?)
There was a problem hiding this comment.
I wonder if
del self.key_to_current_writer.pop[key]would work here?
Looks like it should?
Is it possible for self.key_to_current_writer.get(key) to change between line 637 and 638? (I don't think so---there shouldn't be another thread accessing this?)
I don't think so either. The ReadWriteLock is designed to be async-safe, but not thread safe.
| h = self.provider | ||
|
|
||
| def force_load_metadata() -> Awaitable[None]: | ||
| def force_load_metadata() -> "OpenIDProviderMetadata": |
There was a problem hiding this comment.
This one is mine. I think this fix is correct(?)
|
|
||
| def test_client_sends_body(self): | ||
| defer.ensureDeferred( | ||
| defer.ensureDeferred( # type: ignore[unused-awaitable] |
There was a problem hiding this comment.
Should this have a self.get_success around it? Or is the self.pump below sufficient to ensure this gets called?
There was a problem hiding this comment.
ensureDeferred will run the async function up until the first blocking await, ie. it should be fine.
| events = [Mock(event_id="e1"), Mock(event_id="e2")] | ||
| txn_id = 5 | ||
| self._set_state(self.as_list[0]["id"], ApplicationServiceState.UP) | ||
| self.get_success( |
There was a problem hiding this comment.
Also not sure if this needs to be here? 🤷
| cache: DeferredCache[str, int] = DeferredCache("test") | ||
| with self.assertRaises(KeyError): | ||
| cache.get("foo") | ||
| cache.get("foo") # type: ignore[unused-awaitable] |
There was a problem hiding this comment.
AFAICS cache is roughly a clever Mapping[str, Deferred] throughout this file, and we're checking that we can get and set its contents. It's okay that we're not awaiting on them. But please double-check this.
nb: we're supposed to await |
Huh, thanks. That's news to me---the docstring at synapse/synapse/logging/context.py Lines 797 to 800 in d8cc86e run_in_background.
|
Do you mean specifically using the Also, are the examples of using run_in_background in https://matrix-org.github.io/synapse/latest/development/synapse_architecture/cancellation.html#uncancelled-processing correct? |
the
Good question. I think those are fine because there's an implicit wait for the task to finish (or at least hit the ... actually maybe those examples aren't okay. They'll certainly not re-start any finished logging contexts, but the active logging context will get marked as finished inside the |
squahtx
left a comment
There was a problem hiding this comment.
In principle I like the idea of turning this check on. But there are an awful large number of false positives, which are easy to get fatigued by. I'm also fairly sure we shouldn't be discarding the result of run_in_background.
| defer.ensureDeferred( # type: ignore[unused-awaitable] | ||
| run_as_background_process("background_updates", run_background_updates) | ||
| ) |
There was a problem hiding this comment.
I suspect that we can remove the ensureDeferred call.
| # `new_defer.callback()` call above. | ||
| if self.key_to_current_writer.get(key) == new_defer: | ||
| self.key_to_current_writer.pop(key) | ||
| self.key_to_current_writer.pop(key) # type: ignore[unused-awaitable] |
There was a problem hiding this comment.
I wonder if
del self.key_to_current_writer.pop[key]would work here?
Looks like it should?
Is it possible for self.key_to_current_writer.get(key) to change between line 637 and 638? (I don't think so---there shouldn't be another thread accessing this?)
I don't think so either. The ReadWriteLock is designed to be async-safe, but not thread safe.
|
|
||
| def test_client_sends_body(self): | ||
| defer.ensureDeferred( | ||
| defer.ensureDeferred( # type: ignore[unused-awaitable] |
There was a problem hiding this comment.
ensureDeferred will run the async function up until the first blocking await, ie. it should be fine.
| events = [Mock(event_id="e1"), Mock(event_id="e2")] | ||
| txn_id = 5 | ||
| self._set_state(self.as_list[0]["id"], ApplicationServiceState.UP) | ||
| self.get_success( |
Co-authored-by: David Robertson <davidr@element.io>
I am unsure what to do about that. |
That's probably the best way forward right now. Though I'd note that this has some implications regarding where resource usage is accounted under in metrics, and also makes it harder to determine which request kicked off which bit of processing. |
|
We've had this on our board for a while and I don't think we have the bandwidth to drive it forward. I'd love to see this fixed and I think we've learned useful information from this, but I think we should park this for now. If anyone gets time to look at this in the future, I'd suggest tackling one of the classes identified in #14519 (review) to hopefully make a smaller PR. |
Since I got bitten already twice by this, let's see if this check makes sense.
This is to be reviewed on a per commit basis.
Each commit is handling a different type of ignorable reported error.
There are also a couple of commits that look more like small actual bugs than false positives.
Pull Request Checklist
(run the linters)