Skip to content

Commit b8ab4a9

Browse files
committed
fix Overflow in download analysis metadata
1 parent b648221 commit b8ab4a9

File tree

1 file changed

+26
-4
lines changed

1 file changed

+26
-4
lines changed

qiita_db/handlers/analysis.py

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@
66
# The full license is in the file LICENSE, distributed with this software.
77
# -----------------------------------------------------------------------------
88

9+
from tornado import gen
910
from tornado.web import HTTPError
11+
from iostream import StreamClosedError
12+
from json import dumps
1013

1114
import qiita_db as qdb
1215
from .oauth2 import OauthBaseHandler, authenticate_oauth
@@ -44,7 +47,7 @@ def _get_analysis(a_id):
4447

4548
class APIAnalysisMetadataHandler(OauthBaseHandler):
4649
@authenticate_oauth
47-
def get(self, analysis_id):
50+
async def get(self, analysis_id):
4851
"""Retrieves the analysis metadata
4952
5053
Parameters
@@ -56,15 +59,34 @@ def get(self, analysis_id):
5659
-------
5760
dict
5861
The contents of the analysis keyed by sample id
62+
63+
Notes
64+
-----
65+
This response needed to be broken in chunks because we were hitting
66+
the max size of a respose: 2G; based on: https://bit.ly/3CPvyjd
5967
"""
68+
chunk_len = 1024 * 1024 * 1 # 1 MiB
69+
6070
with qdb.sql_connection.TRN:
6171
a = _get_analysis(analysis_id)
6272
mf_fp = qdb.util.get_filepath_information(
6373
a.mapping_file)['fullpath']
64-
response = None
6574
if mf_fp is not None:
6675
df = qdb.metadata_template.util.load_template_to_dataframe(
6776
mf_fp, index='#SampleID')
68-
response = df.to_dict(orient='index')
77+
response = dumps(df.to_dict(orient='index'))
6978

70-
self.write(response)
79+
crange = range(chunk_len, len(response)+chunk_len, chunk_len)
80+
for i, (win) in enumerate(crange):
81+
chunk = response[i*chunk_len:win]
82+
try:
83+
self.write(chunk)
84+
await self.flush()
85+
except StreamClosedError:
86+
break
87+
finally:
88+
del chunk
89+
# pause the coroutine so other handlers can run
90+
await gen.sleep(0.000000001) # 1 nanosecond
91+
else:
92+
self.write(None)

0 commit comments

Comments
 (0)