Skip to content

Commit

Permalink
use redis_lock
Browse files Browse the repository at this point in the history
  • Loading branch information
sainak committed Jul 17, 2024
1 parent f5c1f09 commit 2b13232
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 109 deletions.
1 change: 1 addition & 0 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ redis-om = "==0.3.1"
requests = "==2.32.3"
sentry-sdk = "==2.5.1"
whitenoise = "==6.6.0"
python-redis-lock = {extras = ["django"], version = "==4.0.0"}

[dev-packages]
black = "==24.4.2"
Expand Down
20 changes: 15 additions & 5 deletions Pipfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

204 changes: 104 additions & 100 deletions care/facility/api/serializers/patient_consultation.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from datetime import timedelta

from django.conf import settings
from django.core.cache import cache
from django.db import transaction
from django.utils import timezone
from django.utils.timezone import localtime, make_aware, now
Expand Down Expand Up @@ -191,6 +192,9 @@ def get_discharge_prn_prescription(self, consultation):
dosage_type=PrescriptionDosageType.PRN.value,
).values()

def _lock_key(self, patient_id):
return f"patient_consultation__patient_registration__{patient_id}"

class Meta:
model = PatientConsultation
read_only_fields = TIMESTAMP_FIELDS + (
Expand Down Expand Up @@ -370,127 +374,127 @@ def create(self, validated_data):

# End Authorisation Checks

patient = PatientRegistration.objects.select_for_update().get(
id=validated_data["patient"].id
)

if patient.last_consultation:
if patient.last_consultation.assigned_to == user:
raise ValidationError(
{
"Permission Denied": "Only Facility Staff can create consultation for a Patient"
},
)
with cache.lock(
self._lock_key(validated_data["patient"].id), expire=30, auto_renewal=True
):
patient = PatientRegistration.objects.get(id=validated_data["patient"].id)
if patient.last_consultation:
if patient.last_consultation.assigned_to == user:
raise ValidationError(
{
"Permission Denied": "Only Facility Staff can create consultation for a Patient"
},
)

if not patient.last_consultation.discharge_date:
raise ValidationError(
{"consultation": "Exists please Edit Existing Consultation"}
)
if not patient.last_consultation.discharge_date:
raise ValidationError(
{"consultation": "Exists please Edit Existing Consultation"}
)

if "is_kasp" in validated_data:
if validated_data["is_kasp"]:
validated_data["kasp_enabled_date"] = now()
if "is_kasp" in validated_data:
if validated_data["is_kasp"]:
validated_data["kasp_enabled_date"] = now()

# Coercing facility as the patient's facility
validated_data["facility_id"] = patient.facility_id
# Coercing facility as the patient's facility
validated_data["facility_id"] = patient.facility_id

consultation: PatientConsultation = super().create(validated_data)
consultation.created_by = user
consultation.last_edited_by = user
consultation.previous_consultation = patient.last_consultation
last_consultation = patient.last_consultation
if (
last_consultation
and consultation.suggestion == SuggestionChoices.A
and last_consultation.suggestion == SuggestionChoices.A
and last_consultation.discharge_date
and last_consultation.discharge_date + timedelta(days=30)
> consultation.encounter_date
):
consultation.is_readmission = True
consultation: PatientConsultation = super().create(validated_data)
consultation.created_by = user
consultation.last_edited_by = user
consultation.previous_consultation = patient.last_consultation
last_consultation = patient.last_consultation
if (
last_consultation
and consultation.suggestion == SuggestionChoices.A
and last_consultation.suggestion == SuggestionChoices.A
and last_consultation.discharge_date
and last_consultation.discharge_date + timedelta(days=30)
> consultation.encounter_date
):
consultation.is_readmission = True

diagnosis = ConsultationDiagnosis.objects.bulk_create(
[
ConsultationDiagnosis(
consultation=consultation,
diagnosis_id=obj["diagnosis"].id,
is_principal=obj["is_principal"],
verification_status=obj["verification_status"],
created_by=user,
)
for obj in create_diagnosis
]
)

diagnosis = ConsultationDiagnosis.objects.bulk_create(
[
ConsultationDiagnosis(
symptoms = EncounterSymptom.objects.bulk_create(
EncounterSymptom(
consultation=consultation,
diagnosis_id=obj["diagnosis"].id,
is_principal=obj["is_principal"],
verification_status=obj["verification_status"],
symptom=obj.get("symptom"),
onset_date=obj.get("onset_date"),
cure_date=obj.get("cure_date"),
clinical_impression_status=obj.get("clinical_impression_status"),
other_symptom=obj.get("other_symptom") or "",
created_by=user,
)
for obj in create_diagnosis
]
)

symptoms = EncounterSymptom.objects.bulk_create(
EncounterSymptom(
consultation=consultation,
symptom=obj.get("symptom"),
onset_date=obj.get("onset_date"),
cure_date=obj.get("cure_date"),
clinical_impression_status=obj.get("clinical_impression_status"),
other_symptom=obj.get("other_symptom") or "",
created_by=user,
)
for obj in create_symptoms
)

bed = validated_data.pop("bed", None)
if bed and consultation.suggestion == SuggestionChoices.A:
consultation_bed = ConsultationBed(
bed=bed,
consultation=consultation,
start_date=consultation.created_date,
for obj in create_symptoms
)
consultation_bed.save()
consultation.current_bed = consultation_bed

if consultation.suggestion == SuggestionChoices.OP:
consultation.discharge_date = now()
patient.is_active = False
patient.allow_transfer = True
else:
patient.is_active = True
patient.last_consultation = consultation
bed = validated_data.pop("bed", None)
if bed and consultation.suggestion == SuggestionChoices.A:
consultation_bed = ConsultationBed(
bed=bed,
consultation=consultation,
start_date=consultation.created_date,
)
consultation_bed.save()
consultation.current_bed = consultation_bed

if action != -1:
patient.action = action
if consultation.suggestion == SuggestionChoices.OP:
consultation.discharge_date = now()
patient.is_active = False
patient.allow_transfer = True
else:
patient.is_active = True
patient.last_consultation = consultation

if review_interval > 0:
patient.review_time = now() + timedelta(minutes=review_interval)
else:
patient.review_time = None
if action != -1:
patient.action = action

consultation.save()
patient.save()
if review_interval > 0:
patient.review_time = now() + timedelta(minutes=review_interval)
else:
patient.review_time = None

create_consultation_events(
consultation.id,
(consultation, *diagnosis, *symptoms),
consultation.created_by.id,
consultation.created_date,
)
consultation.save()
patient.save()

NotificationGenerator(
event=Notification.Event.PATIENT_CONSULTATION_CREATED,
caused_by=user,
caused_object=consultation,
facility=patient.facility,
).generate()
create_consultation_events(
consultation.id,
(consultation, *diagnosis, *symptoms),
consultation.created_by.id,
consultation.created_date,
)

if consultation.assigned_to:
NotificationGenerator(
event=Notification.Event.PATIENT_CONSULTATION_ASSIGNMENT,
event=Notification.Event.PATIENT_CONSULTATION_CREATED,
caused_by=user,
caused_object=consultation,
facility=consultation.patient.facility,
notification_mediums=[
Notification.Medium.SYSTEM,
Notification.Medium.WHATSAPP,
],
facility=patient.facility,
).generate()

return consultation
if consultation.assigned_to:
NotificationGenerator(
event=Notification.Event.PATIENT_CONSULTATION_ASSIGNMENT,
caused_by=user,
caused_object=consultation,
facility=consultation.patient.facility,
notification_mediums=[
Notification.Medium.SYSTEM,
Notification.Medium.WHATSAPP,
],
).generate()

return consultation

def validate_create_diagnoses(self, value):
# Reject if create_diagnoses is present for edits
Expand Down
5 changes: 1 addition & 4 deletions config/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,10 @@
# https://docs.djangoproject.com/en/dev/ref/settings/#caches
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"BACKEND": "redis_lock.django_cache.RedisCache",
"LOCATION": REDIS_URL,
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
# Mimicing memcache behavior.
# http://niwinz.github.io/django-redis/latest/#_memcached_exceptions_behavior
"IGNORE_EXCEPTIONS": True,
},
}
}
Expand Down

0 comments on commit 2b13232

Please sign in to comment.