Skip to content

Commit

Permalink
handle exceptions raised due to cache miss
Browse files Browse the repository at this point in the history
  • Loading branch information
sainak committed Dec 28, 2023
1 parent 0cbf284 commit d8cfae1
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 0 deletions.
9 changes: 9 additions & 0 deletions care/facility/management/commands/load_redis_index.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from django.core.cache import cache
from django.core.management import BaseCommand

from care.facility.static_data.icd11 import load_icd11_diagnosis
Expand All @@ -14,6 +15,14 @@ class Command(BaseCommand):
help = "Loads static data to redis"

def handle(self, *args, **options):
if cache.get("redis_index_loading"):
print("Redis Index already loading, skipping")
return

cache.set("redis_index_loading", True, timeout=60 * 5)

load_icd11_diagnosis()
load_medibase_medicines()
load_pmjy_packages()

cache.delete("redis_index_loading")
6 changes: 6 additions & 0 deletions care/facility/tasks/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from care.facility.tasks.asset_monitor import check_asset_status
from care.facility.tasks.cleanup import delete_old_notifications
from care.facility.tasks.plausible_stats import capture_goals
from care.facility.tasks.redis_index import load_redis_index
from care.facility.tasks.summarisation import (
summarise_district_patient,
summarise_facility_capacity,
Expand Down Expand Up @@ -55,3 +56,8 @@ def setup_periodic_tasks(sender, **kwargs):
capture_goals.s(),
name="capture_goals",
)
sender.add_periodic_task(
crontab(hour="*", minute="0"),
load_redis_index.s(),
name="load_redis_index",
)
32 changes: 32 additions & 0 deletions care/facility/tasks/redis_index.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from logging import Logger

from celery import shared_task
from celery.utils.log import get_task_logger
from django.core.cache import cache

from care.facility.static_data.icd11 import load_icd11_diagnosis
from care.facility.static_data.medibase import load_medibase_medicines
from care.hcx.static_data.pmjy_packages import load_pmjy_packages
from care.utils.static_data.models.base import index_exists

logger: Logger = get_task_logger(__name__)


@shared_task
def load_redis_index():
if cache.get("redis_index_loading"):
logger.info("Redis Index already loading, skipping")
return

cache.set("redis_index_loading", True, timeout=60 * 2)
logger.info("Loading Redis Index")
if index_exists():
logger.info("Index already exists, skipping")
return

load_icd11_diagnosis()
load_medibase_medicines()
load_pmjy_packages()

cache.delete("redis_index_loading")
logger.info("Redis Index Loaded")
13 changes: 13 additions & 0 deletions care/utils/static_data/models/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,22 @@

from django.conf import settings
from redis_om import HashModel, get_redis_connection
from redis_om.model.migrations.migrator import schema_hash_key


class BaseRedisModel(HashModel, ABC):
class Meta:
database = get_redis_connection(url=settings.REDIS_URL)
global_key_prefix = "care_static_data"


def index_exists(model: HashModel = None):
"""
Checks the existence of a redisearch index.
If no model is passed, it checks for the existence of any index.
"""

conn = get_redis_connection(url=settings.REDIS_URL)
if model:
return conn.exists(schema_hash_key(model.Meta.index_name))
return len(conn.execute_command("FT._LIST"))
20 changes: 20 additions & 0 deletions config/exception_handler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from celery import current_app
from django.core.exceptions import ValidationError as DjangoValidationError
from redis_om.model.model import NotFoundError as RedisModelNotFoundError
from rest_framework.exceptions import APIException
from rest_framework.exceptions import ValidationError as DRFValidationError
from rest_framework.fields import get_error_detail
from rest_framework.views import exception_handler as drf_exception_handler


def exception_handler(exc, context):
if isinstance(exc, DjangoValidationError):
exc = DRFValidationError(detail={"detail": get_error_detail(exc)[0]})

elif isinstance(exc, RedisModelNotFoundError):
current_app.send_task("care.facility.tasks.redis_index.load_redis_index")
exc = APIException(
detail={"detail": "Something went wrong, please try after a few seconds."}
)

return drf_exception_handler(exc, context)
1 change: 1 addition & 0 deletions config/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,7 @@
"PAGE_SIZE": 14,
"SEARCH_PARAM": "search_text",
"DEFAULT_SCHEMA_CLASS": "care.utils.schema.AutoSchema",
"EXCEPTION_HANDLER": "config.exception_handler.exception_handler",
}

# drf-spectacular (schema generation)
Expand Down

0 comments on commit d8cfae1

Please sign in to comment.