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:
|
for key in keys:
|
||||||
key_type = DatabaseClient.get_key_type(client, key)
|
key_type = DatabaseClient.get_key_type(client, key)
|
||||||
|
try:
|
||||||
if key_type == "string":
|
if key_type == "string":
|
||||||
value = client.string_ops.string_get(key)
|
value = client.string_ops.string_get(key)
|
||||||
if value is not None:
|
if value is not None:
|
||||||
strings.append({"key": key, "value": value})
|
strings.append({"key": key, "value": value})
|
||||||
elif key_type == "list":
|
elif key_type == "list":
|
||||||
value = client.list_ops.list_range(key, 0, -1)
|
list_values = client.list_ops.list_range(key, 0, -1)
|
||||||
if value is not None:
|
if list_values is not None:
|
||||||
is_email = 'email' in key.lower()
|
processed_value = KeyService.process_list_values(list_values)
|
||||||
processed_value = KeyService.process_list_values(value, is_email)
|
|
||||||
lists.append({"key": key, "value": processed_value})
|
lists.append({"key": key, "value": processed_value})
|
||||||
elif key_type == "hash":
|
elif key_type == "hash":
|
||||||
value = client.hash_ops.hash_get_all(key)
|
hash_values = client.hash_ops.hash_get_all(key)
|
||||||
if value is not None:
|
if hash_values is not None:
|
||||||
processed_value = KeyService.parse_hash_data(value)
|
processed_value = KeyService.parse_hash_data(hash_values)
|
||||||
hashes.append({"key": key, "value": processed_value})
|
hashes.append({"key": key, "value": processed_value})
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"Error processing key {key}: {e}")
|
||||||
|
|
||||||
return jsonify({
|
return jsonify({
|
||||||
'success': True,
|
'success': True,
|
||||||
@ -90,15 +92,22 @@ def get_key_value(key):
|
|||||||
}), 404
|
}), 404
|
||||||
|
|
||||||
value = None
|
value = None
|
||||||
|
try:
|
||||||
if key_type == "string":
|
if key_type == "string":
|
||||||
value = client.string_ops.string_get(key)
|
value = client.string_ops.string_get(key)
|
||||||
elif key_type == "hash":
|
elif key_type == "hash":
|
||||||
value = client.hash_ops.hash_get_all(key)
|
hash_values = client.hash_ops.hash_get_all(key)
|
||||||
value = KeyService.parse_hash_data(value)
|
value = KeyService.parse_hash_data(hash_values)
|
||||||
elif key_type == "list":
|
elif key_type == "list":
|
||||||
value = client.list_ops.list_range(key, 0, -1)
|
list_values = client.list_ops.list_range(key, 0, -1)
|
||||||
is_email = 'email' in key.lower()
|
value = KeyService.process_list_values(list_values)
|
||||||
value = KeyService.process_list_values(value, is_email)
|
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({
|
return jsonify({
|
||||||
'success': True,
|
'success': True,
|
||||||
|
@ -3,33 +3,40 @@ from .logger import logger
|
|||||||
class KeyService:
|
class KeyService:
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def parse_hash_data(hash_data):
|
def parse_hash_data(hash_data):
|
||||||
properly_parsed_hash = {}
|
"""
|
||||||
|
Process hash data from Redis.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
hash_data: Hash data from Redis, should be a dictionary
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Processed dictionary of hash fields and values
|
||||||
|
"""
|
||||||
|
if hash_data is None:
|
||||||
|
return {}
|
||||||
|
|
||||||
|
try:
|
||||||
if isinstance(hash_data, dict):
|
if isinstance(hash_data, dict):
|
||||||
all_pairs = []
|
return {k: KeyService._parse_value(v) for k, v in hash_data.items()}
|
||||||
for k in hash_data.keys():
|
return hash_data
|
||||||
if '=' in k:
|
except Exception as e:
|
||||||
all_pairs.append(k)
|
logger.error(f"Error parsing hash data: {e}")
|
||||||
for v in hash_data.values():
|
return {} if hash_data is None else hash_data
|
||||||
if isinstance(v, str) and '=' in v:
|
|
||||||
all_pairs.append(v)
|
|
||||||
|
|
||||||
for pair in all_pairs:
|
|
||||||
if '=' in pair:
|
|
||||||
field, value = pair.split('=', 1)
|
|
||||||
properly_parsed_hash[field.strip()] = KeyService._parse_value(value.strip())
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _parse_value(value):
|
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(']'):
|
if value.startswith('[') and value.endswith(']'):
|
||||||
try:
|
try:
|
||||||
array_str = value[1:-1]
|
array_str = value[1:-1]
|
||||||
@ -42,28 +49,35 @@ class KeyService:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def clean_redis_value(value):
|
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[1:].strip()
|
||||||
return value
|
return value
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def format_list(values):
|
def process_list_values(values):
|
||||||
formatted_items = []
|
"""
|
||||||
for i in range(0, len(values), 2):
|
Process list values.
|
||||||
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
|
Args:
|
||||||
def process_list_values(values, is_email=False):
|
values: List of values to process
|
||||||
if is_email and len(values) >= 2 and len(values) % 2 == 0:
|
|
||||||
return KeyService.format_list(values)
|
Returns:
|
||||||
else:
|
Processed list of values
|
||||||
cleaned_values = []
|
"""
|
||||||
for v in values:
|
if values is None:
|
||||||
cleaned_v = KeyService.clean_redis_value(v)
|
return []
|
||||||
cleaned_values.append(cleaned_v)
|
|
||||||
return cleaned_values
|
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]
|
[project]
|
||||||
name = "firefly-viewer"
|
name = "firefly-viewer"
|
||||||
version = "1.0.3"
|
version = "1.0.4"
|
||||||
description = "A web-based viewer for Firefly databases"
|
description = "A web-based viewer for Firefly databases"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
authors = [{ name = "IDSolutions", email = "info@innovativedevsolutions.org" }]
|
authors = [{ name = "IDSolutions", email = "info@innovativedevsolutions.org" }]
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
Flask
|
Flask
|
||||||
redis
|
|
||||||
python-dotenv
|
python-dotenv
|
||||||
ifireflylib
|
ifireflylib
|
||||||
click
|
click
|
||||||
|
2
setup.py
2
setup.py
@ -8,7 +8,7 @@ with open("requirements.txt", "r", encoding="utf-8") as fh:
|
|||||||
|
|
||||||
setup(
|
setup(
|
||||||
name="firefly-viewer",
|
name="firefly-viewer",
|
||||||
version="1.0.3",
|
version="1.0.4",
|
||||||
author="IDSolutions",
|
author="IDSolutions",
|
||||||
author_email="info@innovativedevsolutions.org",
|
author_email="info@innovativedevsolutions.org",
|
||||||
description="A web-based viewer for Firefly databases",
|
description="A web-based viewer for Firefly databases",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user