api: allow uncached content fetching.

- this is mostly to optimize for memory of indexer
This commit is contained in:
Marcin Kuzminski 2019-02-14 10:49:02 +01:00
parent ef7b0fcbd5
commit 3871bc6f15
3 changed files with 44 additions and 16 deletions

View file

@ -504,7 +504,8 @@ def get_repo_nodes(request, apiuser, repoid, revision, root_path,
@jsonrpc_method()
def get_repo_file(request, apiuser, repoid, commit_id, file_path,
max_file_bytes=Optional(None), details=Optional('basic')):
max_file_bytes=Optional(None), details=Optional('basic'),
cache=Optional(True)):
"""
Returns a single file from repository at given revision.
@ -523,8 +524,10 @@ def get_repo_file(request, apiuser, repoid, commit_id, file_path,
The valid options are ``minimal`` ``basic`` and ``full``.
:type details: Optional(str)
:param max_file_bytes: Only return file content under this file size bytes
:type details: Optional(int)
:type max_file_bytes: Optional(int)
:param cache: Use internal caches for fetching files. If disabled fetching
files is slower but more memory efficient
:type cache: Optional(bool)
Example output:
.. code-block:: bash
@ -549,6 +552,7 @@ def get_repo_file(request, apiuser, repoid, commit_id, file_path,
_perms = ('repository.admin', 'repository.write', 'repository.read',)
validate_repo_permissions(apiuser, repoid, repo, _perms)
cache = Optional.extract(cache, binary=True)
details = Optional.extract(details)
_extended_types = ['minimal', 'minimal+search', 'basic', 'full']
if details not in _extended_types:
@ -574,7 +578,7 @@ def get_repo_file(request, apiuser, repoid, commit_id, file_path,
node = ScmModel().get_node(
repo, commit_id, file_path, extended_info=extended_info,
content=content, max_file_bytes=max_file_bytes)
content=content, max_file_bytes=max_file_bytes, cache=cache)
except Exception:
log.exception("Exception occurred while trying to get repo node")

View file

@ -381,16 +381,25 @@ class FileNode(Node):
Returns md5, binary flag of the file node, without any cache usage.
"""
if self.commit:
content = self.commit.get_file_content(self.path)
else:
content = self._content
content = self.content_uncached()
is_binary = content and '\0' in content
size = 0
if content:
size = len(content)
return is_binary, md5(content), size
return is_binary, md5(content), size, content
def content_uncached(self):
"""
Returns lazily content of the FileNode. If possible, would try to
decode content from UTF-8.
"""
if self.commit:
content = self.commit.get_file_content(self.path)
else:
content = self._content
return content
@LazyProperty
def content(self):

View file

@ -583,7 +583,7 @@ class ScmModel(BaseModel):
return _dirs, _files
def get_node(self, repo_name, commit_id, file_path,
extended_info=False, content=False, max_file_bytes=None):
extended_info=False, content=False, max_file_bytes=None, cache=True):
"""
retrieve single node from commit
"""
@ -606,12 +606,21 @@ class ScmModel(BaseModel):
if extended_info:
file_data.update({
"md5": file_node.md5,
"binary": file_node.is_binary,
"size": file_node.size,
"extension": file_node.extension,
"mimetype": file_node.mimetype,
"lines": file_node.lines()[0]
})
if cache:
md5 = file_node.md5
is_binary = file_node.is_binary
size = file_node.size
else:
is_binary, md5, size, _content = file_node.metadata_uncached()
file_data.update({
"md5": md5,
"binary": is_binary,
"size": size,
})
if content:
@ -619,7 +628,13 @@ class ScmModel(BaseModel):
and file_node.size > max_file_bytes)
full_content = None
if not file_node.is_binary and not over_size_limit:
full_content = safe_str(file_node.content)
if cache:
full_content = safe_str(file_node.content)
else:
if _content is None:
is_binary, md5, size, _content = \
file_node.metadata_uncached()
full_content = safe_str(_content)
file_data.update({
"content": full_content,
@ -647,7 +662,7 @@ class ScmModel(BaseModel):
for f in files:
_content = None
_data = f_name = f.unicode_path
is_binary, md5, size = f.metadata_uncached()
is_binary, md5, size, _content = f.metadata_uncached()
_data = {
"name": h.escape(f_name),
"md5": md5,