Skip to content

Comments

created a generate token handler#3522

Open
khavinshankar wants to merge 1 commit intoohcnetwork:developfrom
khavinshankar:khavinshankar/refactor/generate-token-handler
Open

created a generate token handler#3522
khavinshankar wants to merge 1 commit intoohcnetwork:developfrom
khavinshankar:khavinshankar/refactor/generate-token-handler

Conversation

@khavinshankar
Copy link
Member

@khavinshankar khavinshankar commented Feb 10, 2026

Proposed Changes

Created a generate token handler to separate out token creation logic, this method is used by plugs.
10bedicu/care_state_hmis#4

Merge Checklist

  • Tests added/fixed
  • Update docs in /docs
  • Linting Complete
  • Any other necessary step

Only PR's with test cases included and passing lint and test pipelines will be reviewed

@ohcnetwork/care-backend-maintainers @ohcnetwork/care-backend-admins

Summary by CodeRabbit

  • Refactor
    • Improved internal token generation workflow in the booking system for enhanced queue management and transaction reliability.

@khavinshankar khavinshankar requested a review from a team as a code owner February 10, 2026 08:17
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 10, 2026

📝 Walkthrough

Walkthrough

This pull request extracts token generation logic into a dedicated classmethod generate_token_handler on the TokenBookingViewSet. The refactoring shifts queue resolution, token creation, and database transaction handling from the existing generate_token method to this new encapsulated handler, which ensures atomicity and manages queue creation when needed.

Changes

Cohort / File(s) Summary
Token generation refactoring
care/emr/api/viewsets/scheduling/booking.py
New classmethod generate_token_handler introduced to centralize token creation logic, queue determination, and atomicity guarantees. Existing generate_token method refactored to delegate token generation responsibilities to the handler while preserving authorization and validation flows.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'created a generate token handler' is vague and generic, using non-descriptive phrasing that doesn't clearly convey what was refactored or why. Consider a more specific title like 'Refactor token creation logic into generate_token_handler method' to better communicate the change.
✅ Passed checks (2 passed)
Check name Status Explanation
Description check ✅ Passed The description includes proposed changes and checklist sections, but lacks an 'Associated Issue' section and provides minimal explanation of the architecture change.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@care/emr/api/viewsets/scheduling/booking.py`:
- Around line 297-315: The code checks TokenQueue.exists() and then creates a
system-generated queue outside the lock, causing a race where two requests can
both create primary queues; replace the separate exists()/create() flow with an
atomic TokenQueue.objects.get_or_create(...) call using the same filters
(facility, resource, date, system_generated=True, name="System Generated") and
supply defaults including is_primary=True only when creating, or wrap the
get_or_create inside the existing lock/transaction.atomic to ensure only one
primary queue is created; update the block that references booking.token_slot,
TokenQueue.objects.filter(...).exists(), .first(), and .create(...) to use
get_or_create with appropriate defaults.
🧹 Nitpick comments (1)
care/emr/api/viewsets/scheduling/booking.py (1)

340-348: Consider extracting token_date calculation to avoid duplication.

The token_date calculation logic (making timezone naive and adding 1 second) appears here and again in generate_token_handler at lines 300-302. While not incorrect, having this logic in two places means any future adjustments would need to be made twice. I'm sure that won't cause any issues down the road.

♻️ Suggested helper extraction
`@staticmethod`
def _get_token_date(slot_start_datetime):
    """Extract token date accounting for timezone edge cases."""
    return timezone.make_naive(
        slot_start_datetime + timedelta(seconds=1)
    ).date()

Then use self._get_token_date(booking.token_slot.start_datetime) in both locations.

Comment on lines +297 to +315
if queue is None:
# slot may start at 1:00 IST (19:30 UTC of previous date), hence
# making it tz naive and adding 1 second to ensure correct date extraction
token_date = timezone.make_naive(
booking.token_slot.start_datetime + timedelta(seconds=1)
).date()
filters = {
"facility": booking.token_slot.resource.facility,
"resource": booking.token_slot.resource,
"date": token_date,
}
queue_exists = TokenQueue.objects.filter(**filters).exists()
filters["system_generated"] = True
queue = TokenQueue.objects.filter(**filters).first()
if not queue:
filters["name"] = "System Generated"
if not queue_exists:
filters["is_primary"] = True
queue = TokenQueue.objects.create(**filters)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Race condition in queue creation logic.

The queue existence check (line 308) and queue creation (line 315) are not atomic and occur outside the lock. Under concurrent requests, two threads could both see queue_exists = False and each create a system-generated queue with is_primary = True, resulting in duplicate queues.

Consider using get_or_create to atomically handle this, or extend the lock scope to include queue resolution.

🔒 Proposed fix using get_or_create
         if queue is None:
             # slot may start at 1:00 IST (19:30 UTC of previous date), hence
             # making it tz naive and adding 1 second to ensure correct date extraction
             token_date = timezone.make_naive(
                 booking.token_slot.start_datetime + timedelta(seconds=1)
             ).date()
             filters = {
                 "facility": booking.token_slot.resource.facility,
                 "resource": booking.token_slot.resource,
                 "date": token_date,
             }
-            queue_exists = TokenQueue.objects.filter(**filters).exists()
-            filters["system_generated"] = True
-            queue = TokenQueue.objects.filter(**filters).first()
-            if not queue:
-                filters["name"] = "System Generated"
-                if not queue_exists:
-                    filters["is_primary"] = True
-                queue = TokenQueue.objects.create(**filters)
+            with transaction.atomic():
+                queue_exists = TokenQueue.objects.filter(**filters).exists()
+                queue, created = TokenQueue.objects.get_or_create(
+                    **filters,
+                    system_generated=True,
+                    defaults={
+                        "name": "System Generated",
+                        "is_primary": not queue_exists,
+                    },
+                )
🤖 Prompt for AI Agents
In `@care/emr/api/viewsets/scheduling/booking.py` around lines 297 - 315, The code
checks TokenQueue.exists() and then creates a system-generated queue outside the
lock, causing a race where two requests can both create primary queues; replace
the separate exists()/create() flow with an atomic
TokenQueue.objects.get_or_create(...) call using the same filters (facility,
resource, date, system_generated=True, name="System Generated") and supply
defaults including is_primary=True only when creating, or wrap the get_or_create
inside the existing lock/transaction.atomic to ensure only one primary queue is
created; update the block that references booking.token_slot,
TokenQueue.objects.filter(...).exists(), .first(), and .create(...) to use
get_or_create with appropriate defaults.

@codecov
Copy link

codecov bot commented Feb 10, 2026

Codecov Report

❌ Patch coverage is 86.95652% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 74.35%. Comparing base (3b80852) to head (8e72d2f).

Files with missing lines Patch % Lines
care/emr/api/viewsets/scheduling/booking.py 86.95% 0 Missing and 3 partials ⚠️
Additional details and impacted files
@@           Coverage Diff            @@
##           develop    #3522   +/-   ##
========================================
  Coverage    74.34%   74.35%           
========================================
  Files          473      473           
  Lines        21877    21884    +7     
  Branches      2281     2282    +1     
========================================
+ Hits         16265    16271    +6     
  Misses        5106     5106           
- Partials       506      507    +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants