Join GitHub today
GitHub is home to over 20 million developers working together to host and review code, manage projects, and build software together.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
Already on GitHub? Sign in to your account
Store Promise<Response> instead of Response for HTTP API transactions #1624
Conversation
Kegsay
added some commits
Nov 10, 2016
Kegsay
added
the
bug
label
Nov 11, 2016
Kegsay
assigned
erikjohnston
Nov 11, 2016
|
I wondering if a nicer API would be something like: self.transactions.fetch_or_execute(
self.handler.do_foo, txn_id,
arg1, arg2, arg3=arg3
)where |
|
Also, would be totally awesome if |
|
|
|
Also, I don't mind moving it to |
|
I'm guessing you're proposing I make it more generic (so |
Nah, I just made it up.
At the very least it should be moved up, but generally I quite helpers like this to live a bit separately, rather than being dumped alongside the rest servlets themselves
Well, it is currently implemented in a generic fashion. I'm happy for the arg name to be |
Do you want the implementation to be generic or are you happy with it in its current form (accepting |
That's fine i suppose
Oh, I misread. Yeah, ok, I guess the generation of the key is non-trivial. Though I'd still be tempted to move the |
|
SGTM |
|
Hmmm. The old implementation was using transaction IDs as a way to prune the cache, but it means that you couldn't have multiple in-flight requests at the same time and get idempotency, which feels bad. I've removed that code in my fix, but now the cache will grow unbounded. How do you propose I clear the cache? Periodic interval? 10 minutes? The generic form now just takes a key, so I can't be more intelligent like base it off the given user (access_token, which is now concatenated in the key). |
| + of (response_code, response_dict). | ||
| + """ | ||
| + try: | ||
| + return self.transactions[txn_key] |
| + deferred = fn(*args, **kwargs) | ||
| + observable = ObservableDeferred(deferred) | ||
| + self.transactions[txn_key] = observable | ||
| + return observable |
| + observable = self.txns.fetch_or_execute_request( | ||
| + request, self.on_POST, request | ||
| + ) | ||
| + res = yield observable.observe() |
erikjohnston
Nov 12, 2016
Owner
Ah, I'd move this .observe() up into the actual cache to make things neater:
def on_PUT(self, request, txn_id):
return self.txns.fetch_or_execute_request(
request, self.on_POST, request
)
For now, I'd probably expire after 30mins (10 is probably a bit on the low side). Ideally I'd guess we'd probably batch persist these txn_ids to the db so they survive restarts, and then purge that table after a few hours/days. |
|
(Also, a python test case for the |
Kegsay
added some commits
Nov 14, 2016
For cleaning entries, I'm just periodically checking every 30 minutes, and timestamping when functions were invoked (which means the actual time in the cache is between 30~60 minutes). This feels simpler and less wasteful compared to registering timeouts for each entry in the cache, which has comparatively more function call overhead. |
|
@erikjohnston PTAL Also, are the Dendron tests just flakey or should I be worried? Looking at the previous builds on http://matrix.org/jenkins/job/SynapseSytestDendronCommit/ makes me think flakey, but I don't know. |
Yes :( |
|
LGTM |
Kegsay commentedNov 11, 2016
This fixes a race whereby:
This race is common in the wild when Synapse is struggling under load.
This commit fixes the race by:
Now with bonus sytests!