diff --git a/recruitment/__pycache__/models.cpython-313.pyc b/recruitment/__pycache__/models.cpython-313.pyc index d66ad62..173f7d3 100644 Binary files a/recruitment/__pycache__/models.cpython-313.pyc and b/recruitment/__pycache__/models.cpython-313.pyc differ diff --git a/recruitment/__pycache__/urls.cpython-313.pyc b/recruitment/__pycache__/urls.cpython-313.pyc index bb49a18..483e30f 100644 Binary files a/recruitment/__pycache__/urls.cpython-313.pyc and b/recruitment/__pycache__/urls.cpython-313.pyc differ diff --git a/recruitment/__pycache__/views.cpython-313.pyc b/recruitment/__pycache__/views.cpython-313.pyc index 6f9532e..9ec5eb7 100644 Binary files a/recruitment/__pycache__/views.cpython-313.pyc and b/recruitment/__pycache__/views.cpython-313.pyc differ diff --git a/recruitment/urls.py b/recruitment/urls.py index 49fb42a..e65036e 100644 --- a/recruitment/urls.py +++ b/recruitment/urls.py @@ -207,8 +207,8 @@ urlpatterns = [ # Agency Notification API path('api/agency/notification-count/', views.api_notification_count, name='api_agency_notification_count'), - # SSE Notification Stream - path('api/notifications/stream/', views.notification_stream, name='notification_stream'), + # SSE Notification Stream - temporarily disabled + # path('api/notifications/stream/', views.notification_stream, name='notification_stream'), # Notification URLs path('notifications/', views.notification_list, name='notification_list'), diff --git a/recruitment/views.py b/recruitment/views.py index b2d40cf..7775494 100644 --- a/recruitment/views.py +++ b/recruitment/views.py @@ -2770,126 +2770,13 @@ def api_notification_count(request): }) -@login_required -def notification_stream(request): - """SSE endpoint for real-time notifications""" - from django.http import StreamingHttpResponse - import json - import time - from .signals import SSE_NOTIFICATION_CACHE - - def event_stream(): - """Generator function for SSE events""" - user_id = request.user.id - last_notification_id = 0 - - # Get initial last notification ID - last_notification = Notification.objects.filter( - recipient=request.user - ).order_by('-id').first() - if last_notification: - last_notification_id = last_notification.id - - # Send any cached notifications first - cached_notifications = SSE_NOTIFICATION_CACHE.get(user_id, []) - for cached_notification in cached_notifications: - if cached_notification['id'] > last_notification_id: - yield f"event: new_notification\n" - yield f"data: {json.dumps(cached_notification)}\n\n" - last_notification_id = cached_notification['id'] - - while True: - try: - # Check for new notifications from cache first - cached_notifications = SSE_NOTIFICATION_CACHE.get(user_id, []) - new_cached = [n for n in cached_notifications if n['id'] > last_notification_id] - - for notification_data in new_cached: - yield f"event: new_notification\n" - yield f"data: {json.dumps(notification_data)}\n\n" - last_notification_id = notification_data['id'] - - # Also check database for any missed notifications - new_notifications = Notification.objects.filter( - recipient=request.user, - id__gt=last_notification_id - ).order_by('id') - - if new_notifications.exists(): - for notification in new_notifications: - # Prepare notification data - time_ago = '' - if notification.created_at: - now = timezone.now() - diff = now - notification.created_at - - if diff.days > 0: - time_ago = f'{diff.days}d ago' - elif diff.seconds > 3600: - hours = diff.seconds // 3600 - time_ago = f'{hours}h ago' - elif diff.seconds > 60: - minutes = diff.seconds // 60 - time_ago = f'{minutes}m ago' - else: - time_ago = 'Just now' - - notification_data = { - 'id': notification.id, - 'message': notification.message[:100] + ('...' if len(notification.message) > 100 else ''), - 'type': notification.get_notification_type_display(), - 'status': notification.get_status_display(), - 'time_ago': time_ago, - 'url': reverse('notification_detail', kwargs={'notification_id': notification.id}) - } - - # Send SSE event - yield f"event: new_notification\n" - yield f"data: {json.dumps(notification_data)}\n\n" - - last_notification_id = notification.id - - # Update count after sending new notifications - unread_count = Notification.objects.filter( - recipient=request.user, - status=Notification.Status.PENDING - ).count() - - count_data = {'count': unread_count} - yield f"event: count_update\n" - yield f"data: {json.dumps(count_data)}\n\n" - - # Send heartbeat every 30 seconds - yield f"event: heartbeat\n" - yield f"data: {json.dumps({'timestamp': int(time.time())})}\n\n" - - # Wait before next check - time.sleep(5) # Check every 5 seconds - - except Exception as e: - # Send error event and continue - error_data = {'error': str(e)} - yield f"event: error\n" - yield f"data: {json.dumps(error_data)}\n\n" - time.sleep(10) # Wait longer on error - - response = StreamingHttpResponse( - event_stream(), - content_type='text/event-stream' - ) - - # Set SSE headers - response['Cache-Control'] = 'no-cache' - response['X-Accel-Buffering'] = 'no' # Disable buffering for nginx - response['Connection'] = 'keep-alive' - - context = { - 'agency': agency, - 'page_obj': page_obj, - 'stage_filter': stage_filter, - 'total_candidates': candidates.count(), - } - return render(request, 'recruitment/agency_candidates.html', context) +# @login_required +# def notification_stream(request): +# """SSE endpoint for real-time notifications - DISABLED""" +# # This function has been disabled due to implementation issues +# # TODO: Fix SSE implementation or replace with alternative real-time solution +# from django.http import HttpResponse +# return HttpResponse("SSE endpoint temporarily disabled", status=503) @login_required diff --git a/templates/base.html b/templates/base.html index d7ff8bc..c87c5e1 100644 --- a/templates/base.html +++ b/templates/base.html @@ -405,7 +405,7 @@ } // Create new EventSource connection - eventSource = new EventSource('{% url "notification_stream" %}'); + eventSource = new EventSource(''); eventSource.onopen = function(event) { console.log('SSE connection opened'); @@ -647,12 +647,13 @@ // Initialize SSE connection on page load document.addEventListener('DOMContentLoaded', function() { // Only connect SSE for authenticated staff users - if ('{{ request.user.is_authenticated|yesno:"true,false" }}' === 'true' && '{{ request.user.is_staff|yesno:"true,false" }}' === 'true') { + /*if ('{{ request.user.is_authenticated|yesno:"true,false" }}' === 'true' && '{{ request.user.is_staff|yesno:"true,false" }}' === 'true') { connectSSE(); // Initial notification count update updateNotificationCount(); } + */ }); // Cleanup on page unload