"""Handle service errors.""" import functools import random import time from sentry_sdk import capture_message from src.configs import common_config from src.constants import common_errors from src.constants import common_fields from src.constants import http_statuses from src.utils import error_log def handle_errors(retry_count=common_config.SERVICE_RETRY_COUNT): """Handle microservice errors. This decorator retries several times on errors and sends SNS notification if that does not help. Returns json as dict on successful or None on 404 responses. Args: retry_count (int): times to retry on errors """ def inner(f): @functools.wraps(f) def wrapper(*args, **kwargs): for i in range(0, retry_count): ows_response = f(*args, **kwargs) if (ows_response.status_code >= http_statuses.OK_FROM and ows_response.status_code <= http_statuses.OK_TO): return ows_response.json() if ows_response.status_code == http_statuses.NOT_FOUND: return None time.sleep((2 ** i) + (random.randint(0, 1000) / 1000)) try: body_data = ows_response.json() error_message = body_data.get(common_fields.RESPONSE_MESSAGE) error_code = body_data.get(common_fields.RESPONSE_CODE) except Exception: error_message = None error_code = None msg = common_errors.OWS_REQUEST_ERROR.format( ows_response.status_code, error_code, error_message) error_log.log_error_by_func(msg, f, *args, **kwargs) capture_message(msg, level='error') return wrapper return inner