summary refs log tree commit diff
path: root/synapse/http/server.py
diff options
context:
space:
mode:
authorErik Johnston <erik@matrix.org>2021-09-17 13:48:18 +0100
committerErik Johnston <erik@matrix.org>2021-09-17 14:53:02 +0100
commit40c99c22ff240c65c819e9eaa798b87c8d5afe47 (patch)
tree6e89b6e3e2b4080d9c9110b2d821ff698ddfbb9e /synapse/http/server.py
parentRequire SynapseRequest for respond_with_json (diff)
downloadsynapse-40c99c22ff240c65c819e9eaa798b87c8d5afe47.tar.xz
Add a `_write_json_to_request_in_thread`
Diffstat (limited to 'synapse/http/server.py')
-rw-r--r--synapse/http/server.py30
1 files changed, 29 insertions, 1 deletions
diff --git a/synapse/http/server.py b/synapse/http/server.py

index e28b56abb9..1a47ece395 100644 --- a/synapse/http/server.py +++ b/synapse/http/server.py
@@ -56,7 +56,7 @@ from synapse.api.errors import ( UnrecognizedRequestError, ) from synapse.http.site import SynapseRequest -from synapse.logging.context import preserve_fn +from synapse.logging.context import defer_to_thread, preserve_fn, run_in_background from synapse.logging.opentracing import trace_servlet from synapse.util import json_encoder from synapse.util.caches import intern_dict @@ -809,3 +809,31 @@ def finish_request(request: Request): request.finish() except RuntimeError as e: logger.info("Connection disconnected before response was written: %r", e) + + +def _write_json_to_request_in_thread( + request: SynapseRequest, + json_encoder: Callable[[Any], str], + json_object: Any, +): + """Encodes the given JSON object on a thread and then writes it to the + request. + + This is done so that encoding large JSON objects doesn't block the reactor + thread. + + Note: We don't use JsonEncoder.iterencode here as that falls back to the + Python implementation (rather than the C backend), which is *much* more + expensive. + """ + + async def _inner_encode_in_thread(): + json_str = await defer_to_thread(request.reactor, json_encoder, json_object) + + try: + request.write(json_str) + request.finish() + except RuntimeError as e: + logger.info("Connection disconnected before response was written: %r", e) + + run_in_background(_inner_encode_in_thread)