Fix: Improve data handling and error logging
This commit improves the application's robustness by enhancing data handling and adding error logging. Specifically, it: - Updates the project version to 1.0.4 in `pyproject.toml` and `setup.py`. - Removes redis from requirements.txt - Improves data parsing in `KeyService.parse_hash_data` to handle None values and simplify the logic. - Adds error logging to `KeyService.parse_hash_data` and `KeyService.process_list_values` to catch and log parsing errors. - Modifies `KeyService.process_list_values` to ensure the return value is always a list. - Adds try-except blocks in `get_keys` and `get_key_value` routes to handle potential exceptions during key processing and log warnings.
This commit is contained in:
parent
8774cad94d
commit
aa144c1349
@ -37,21 +37,23 @@ def get_keys():
|
||||
|
||||
for key in keys:
|
||||
key_type = DatabaseClient.get_key_type(client, key)
|
||||
if key_type == "string":
|
||||
value = client.string_ops.string_get(key)
|
||||
if value is not None:
|
||||
strings.append({"key": key, "value": value})
|
||||
elif key_type == "list":
|
||||
value = client.list_ops.list_range(key, 0, -1)
|
||||
if value is not None:
|
||||
is_email = 'email' in key.lower()
|
||||
processed_value = KeyService.process_list_values(value, is_email)
|
||||
lists.append({"key": key, "value": processed_value})
|
||||
elif key_type == "hash":
|
||||
value = client.hash_ops.hash_get_all(key)
|
||||
if value is not None:
|
||||
processed_value = KeyService.parse_hash_data(value)
|
||||
hashes.append({"key": key, "value": processed_value})
|
||||
try:
|
||||
if key_type == "string":
|
||||
value = client.string_ops.string_get(key)
|
||||
if value is not None:
|
||||
strings.append({"key": key, "value": value})
|
||||
elif key_type == "list":
|
||||
list_values = client.list_ops.list_range(key, 0, -1)
|
||||
if list_values is not None:
|
||||
processed_value = KeyService.process_list_values(list_values)
|
||||
lists.append({"key": key, "value": processed_value})
|
||||
elif key_type == "hash":
|
||||
hash_values = client.hash_ops.hash_get_all(key)
|
||||
if hash_values is not None:
|
||||
processed_value = KeyService.parse_hash_data(hash_values)
|
||||
hashes.append({"key": key, "value": processed_value})
|
||||
except Exception as e:
|
||||
logger.warning(f"Error processing key {key}: {e}")
|
||||
|
||||
return jsonify({
|
||||
'success': True,
|
||||
@ -90,15 +92,22 @@ def get_key_value(key):
|
||||
}), 404
|
||||
|
||||
value = None
|
||||
if key_type == "string":
|
||||
value = client.string_ops.string_get(key)
|
||||
elif key_type == "hash":
|
||||
value = client.hash_ops.hash_get_all(key)
|
||||
value = KeyService.parse_hash_data(value)
|
||||
elif key_type == "list":
|
||||
value = client.list_ops.list_range(key, 0, -1)
|
||||
is_email = 'email' in key.lower()
|
||||
value = KeyService.process_list_values(value, is_email)
|
||||
try:
|
||||
if key_type == "string":
|
||||
value = client.string_ops.string_get(key)
|
||||
elif key_type == "hash":
|
||||
hash_values = client.hash_ops.hash_get_all(key)
|
||||
value = KeyService.parse_hash_data(hash_values)
|
||||
elif key_type == "list":
|
||||
list_values = client.list_ops.list_range(key, 0, -1)
|
||||
value = KeyService.process_list_values(list_values)
|
||||
except Exception as e:
|
||||
logger.warning(f"Error processing key {key}: {e}")
|
||||
return jsonify({
|
||||
'success': False,
|
||||
'error': f'Error processing key: {str(e)}',
|
||||
'connection_status': True
|
||||
}), 500
|
||||
|
||||
return jsonify({
|
||||
'success': True,
|
||||
|
@ -3,33 +3,40 @@ from .logger import logger
|
||||
class KeyService:
|
||||
@staticmethod
|
||||
def parse_hash_data(hash_data):
|
||||
properly_parsed_hash = {}
|
||||
"""
|
||||
Process hash data from Redis.
|
||||
|
||||
if isinstance(hash_data, dict):
|
||||
all_pairs = []
|
||||
for k in hash_data.keys():
|
||||
if '=' in k:
|
||||
all_pairs.append(k)
|
||||
for v in hash_data.values():
|
||||
if isinstance(v, str) and '=' in v:
|
||||
all_pairs.append(v)
|
||||
Args:
|
||||
hash_data: Hash data from Redis, should be a dictionary
|
||||
|
||||
for pair in all_pairs:
|
||||
if '=' in pair:
|
||||
field, value = pair.split('=', 1)
|
||||
properly_parsed_hash[field.strip()] = KeyService._parse_value(value.strip())
|
||||
Returns:
|
||||
Processed dictionary of hash fields and values
|
||||
"""
|
||||
if hash_data is None:
|
||||
return {}
|
||||
|
||||
elif isinstance(hash_data, str):
|
||||
lines = hash_data.strip().split('\n')
|
||||
for line in lines:
|
||||
if '=' in line:
|
||||
field, value = line.split('=', 1)
|
||||
properly_parsed_hash[field.strip()] = KeyService._parse_value(value.strip())
|
||||
|
||||
return properly_parsed_hash
|
||||
try:
|
||||
if isinstance(hash_data, dict):
|
||||
return {k: KeyService._parse_value(v) for k, v in hash_data.items()}
|
||||
return hash_data
|
||||
except Exception as e:
|
||||
logger.error(f"Error parsing hash data: {e}")
|
||||
return {} if hash_data is None else hash_data
|
||||
|
||||
@staticmethod
|
||||
def _parse_value(value):
|
||||
"""
|
||||
Parse a value, handling special formats like arrays.
|
||||
|
||||
Args:
|
||||
value: The value to parse
|
||||
|
||||
Returns:
|
||||
Parsed value
|
||||
"""
|
||||
if not isinstance(value, str):
|
||||
return value
|
||||
|
||||
if value.startswith('[') and value.endswith(']'):
|
||||
try:
|
||||
array_str = value[1:-1]
|
||||
@ -42,28 +49,35 @@ class KeyService:
|
||||
|
||||
@staticmethod
|
||||
def clean_redis_value(value):
|
||||
if isinstance(value, str) and value.startswith(('+', '-', ':', '$', '*')):
|
||||
"""
|
||||
Clean a Redis value by removing protocol prefixes.
|
||||
|
||||
Args:
|
||||
value: The Redis value to clean
|
||||
|
||||
Returns:
|
||||
Cleaned value
|
||||
"""
|
||||
if isinstance(value, str) and value.startswith(('+', '-', ':', '`', '*')):
|
||||
return value[1:].strip()
|
||||
return value
|
||||
|
||||
@staticmethod
|
||||
def format_list(values):
|
||||
formatted_items = []
|
||||
for i in range(0, len(values), 2):
|
||||
if i + 1 < len(values):
|
||||
field = KeyService.clean_redis_value(values[i])
|
||||
value = KeyService.clean_redis_value(values[i + 1])
|
||||
field = field.capitalize()
|
||||
formatted_items.append(f"{field}: {value}")
|
||||
return formatted_items
|
||||
|
||||
@staticmethod
|
||||
def process_list_values(values, is_email=False):
|
||||
if is_email and len(values) >= 2 and len(values) % 2 == 0:
|
||||
return KeyService.format_list(values)
|
||||
else:
|
||||
cleaned_values = []
|
||||
for v in values:
|
||||
cleaned_v = KeyService.clean_redis_value(v)
|
||||
cleaned_values.append(cleaned_v)
|
||||
return cleaned_values
|
||||
def process_list_values(values):
|
||||
"""
|
||||
Process list values.
|
||||
|
||||
Args:
|
||||
values: List of values to process
|
||||
|
||||
Returns:
|
||||
Processed list of values
|
||||
"""
|
||||
if values is None:
|
||||
return []
|
||||
|
||||
try:
|
||||
return list(values) # Just ensure it's a list
|
||||
except Exception as e:
|
||||
logger.error(f"Error processing list values: {e}")
|
||||
return values if isinstance(values, list) else []
|
@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "firefly-viewer"
|
||||
version = "1.0.3"
|
||||
version = "1.0.4"
|
||||
description = "A web-based viewer for Firefly databases"
|
||||
readme = "README.md"
|
||||
authors = [{ name = "IDSolutions", email = "info@innovativedevsolutions.org" }]
|
||||
|
@ -1,5 +1,4 @@
|
||||
Flask
|
||||
redis
|
||||
python-dotenv
|
||||
ifireflylib
|
||||
click
|
||||
|
Loading…
x
Reference in New Issue
Block a user