mirror of
https://git.linux-kernel.at/oliver/ivatar.git
synced 2025-11-14 12:08:04 +00:00
Fix performance issues in /deployment/version/ endpoint
- Add proper cache expiration with 5-minute TTL - Optimize git log file reading to avoid loading entire file - Read only last chunk (1024 bytes) instead of all lines - Add shorter TTL (30s) for error cases to allow retry - Improve error handling with UnicodeDecodeError support - Maintain backward compatibility and security (no subprocess calls) This fixes the 30-second response time issue by implementing efficient caching and optimized file I/O operations.
This commit is contained in:
@@ -845,9 +845,11 @@ class StatsView(TemplateView, JsonResponse):
|
|||||||
return JsonResponse(retval)
|
return JsonResponse(retval)
|
||||||
|
|
||||||
|
|
||||||
# Thread-safe version cache
|
# Thread-safe version cache with timestamp
|
||||||
_version_cache = None
|
_version_cache = None
|
||||||
|
_version_cache_timestamp = None
|
||||||
_version_cache_lock = threading.Lock()
|
_version_cache_lock = threading.Lock()
|
||||||
|
_VERSION_CACHE_TTL = 300 # 5 minutes cache TTL
|
||||||
|
|
||||||
|
|
||||||
def _get_git_info_from_files():
|
def _get_git_info_from_files():
|
||||||
@@ -889,15 +891,29 @@ def _get_git_info_from_files():
|
|||||||
branch_name = "detached"
|
branch_name = "detached"
|
||||||
|
|
||||||
# Try to get commit date from git log file (if available)
|
# Try to get commit date from git log file (if available)
|
||||||
|
# Optimize: read only the last line instead of entire file
|
||||||
commit_date = None
|
commit_date = None
|
||||||
log_file = path.join(git_dir, "logs", "HEAD")
|
log_file = path.join(git_dir, "logs", "HEAD")
|
||||||
if path.exists(log_file):
|
if path.exists(log_file):
|
||||||
try:
|
try:
|
||||||
with open(log_file, "r") as f:
|
with open(log_file, "rb") as f:
|
||||||
# Read last line to get most recent commit info
|
# Seek to end and read backwards to find last line
|
||||||
lines = f.readlines()
|
f.seek(0, 2) # Seek to end
|
||||||
if lines:
|
file_size = f.tell()
|
||||||
last_line = lines[-1].strip()
|
|
||||||
|
# Read backwards in chunks to find the last line
|
||||||
|
chunk_size = min(1024, file_size)
|
||||||
|
f.seek(max(0, file_size - chunk_size))
|
||||||
|
chunk = f.read().decode("utf-8", errors="ignore")
|
||||||
|
|
||||||
|
# Find the last newline
|
||||||
|
last_newline = chunk.rfind("\n")
|
||||||
|
if last_newline != -1:
|
||||||
|
last_line = chunk[last_newline + 1:].strip()
|
||||||
|
else:
|
||||||
|
last_line = chunk.strip()
|
||||||
|
|
||||||
|
if last_line:
|
||||||
# Git log format: <old_hash> <new_hash> <author> <timestamp> <timezone> <message>
|
# Git log format: <old_hash> <new_hash> <author> <timestamp> <timezone> <message>
|
||||||
parts = last_line.split("\t")
|
parts = last_line.split("\t")
|
||||||
if len(parts) >= 2:
|
if len(parts) >= 2:
|
||||||
@@ -910,7 +926,7 @@ def _get_git_info_from_files():
|
|||||||
commit_date = datetime.datetime.fromtimestamp(
|
commit_date = datetime.datetime.fromtimestamp(
|
||||||
timestamp
|
timestamp
|
||||||
).strftime("%Y-%m-%d %H:%M:%S %z")
|
).strftime("%Y-%m-%d %H:%M:%S %z")
|
||||||
except (ValueError, IndexError):
|
except (ValueError, IndexError, UnicodeDecodeError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# Fallback: try to get date from commit object if available
|
# Fallback: try to get date from commit object if available
|
||||||
@@ -941,21 +957,33 @@ def _get_git_info_from_files():
|
|||||||
|
|
||||||
def _get_cached_version_info():
|
def _get_cached_version_info():
|
||||||
"""
|
"""
|
||||||
Get cached version information, loading it if not available
|
Get cached version information, loading it if not available or expired
|
||||||
"""
|
"""
|
||||||
global _version_cache
|
global _version_cache, _version_cache_timestamp
|
||||||
|
import time
|
||||||
|
|
||||||
with _version_cache_lock:
|
with _version_cache_lock:
|
||||||
if _version_cache is None:
|
current_time = time.time()
|
||||||
|
|
||||||
|
# Check if cache is expired or doesn't exist
|
||||||
|
if (
|
||||||
|
_version_cache is None
|
||||||
|
or _version_cache_timestamp is None
|
||||||
|
or current_time - _version_cache_timestamp > _VERSION_CACHE_TTL
|
||||||
|
):
|
||||||
|
|
||||||
# Get version info from git files
|
# Get version info from git files
|
||||||
_version_cache = _get_git_info_from_files()
|
_version_cache = _get_git_info_from_files()
|
||||||
|
_version_cache_timestamp = current_time
|
||||||
|
|
||||||
# If that fails, return error
|
# If that fails, return error but don't cache it for long
|
||||||
if _version_cache is None:
|
if _version_cache is None:
|
||||||
_version_cache = {
|
_version_cache = {
|
||||||
"error": "Unable to determine version - .git directory not found",
|
"error": "Unable to determine version - .git directory not found",
|
||||||
"deployment_status": "unknown",
|
"deployment_status": "unknown",
|
||||||
}
|
}
|
||||||
|
# Set shorter TTL for error cases to allow retry
|
||||||
|
_version_cache_timestamp = current_time - _VERSION_CACHE_TTL + 30
|
||||||
|
|
||||||
return _version_cache
|
return _version_cache
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user