da03 commited on
Commit
12c4b52
·
1 Parent(s): 4555c1c
Files changed (2) hide show
  1. dispatcher.py +44 -10
  2. static/index.html +54 -16
dispatcher.py CHANGED
@@ -388,19 +388,15 @@ class SessionManager:
388
  return None
389
 
390
  async def add_session_to_queue(self, session: UserSession):
391
- """Add a session to the queue"""
392
- # Check if queue was empty before adding this session
393
- was_queue_empty = len(self.session_queue) == 0
394
-
395
  self.sessions[session.session_id] = session
396
  self.session_queue.append(session.session_id)
397
  session.status = SessionStatus.QUEUED
398
  session.queue_start_time = time.time()
399
  logger.info(f"Added session {session.session_id} to queue. Queue size: {len(self.session_queue)}")
400
 
401
- # If queue was empty and now has users, apply time limits to existing active sessions
402
- if was_queue_empty and len(self.session_queue) > 0:
403
- await self.apply_queue_limits_to_existing_sessions()
404
 
405
  async def apply_queue_limits_to_existing_sessions(self):
406
  """Apply 60-second time limits to existing unlimited sessions when queue forms"""
@@ -420,11 +416,9 @@ class SessionManager:
420
  # Notify the user about the new time limit
421
  try:
422
  queue_size = len(self.session_queue)
423
- message = f"Other users waiting. Time remaining: 60 seconds."
424
 
425
  await session.websocket.send_json({
426
  "type": "queue_limit_applied",
427
- "message": message,
428
  "time_remaining": 60.0,
429
  "queue_size": queue_size
430
  })
@@ -435,8 +429,39 @@ class SessionManager:
435
  if affected_sessions > 0:
436
  analytics.log_queue_limits_applied(affected_sessions, len(self.session_queue))
437
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
438
  async def process_queue(self):
439
  """Process the session queue"""
 
 
 
440
  while self.session_queue:
441
  session_id = self.session_queue[0]
442
  session = self.sessions.get(session_id)
@@ -462,7 +487,7 @@ class SessionManager:
462
  session.worker_id = worker.worker_id
463
  session.last_activity = time.time()
464
 
465
- # Set session time limit based on queue status
466
  if len(self.session_queue) > 0:
467
  session.max_session_time = self.MAX_SESSION_TIME_WITH_QUEUE
468
  session.session_limit_start_time = time.time() # Track when limit started
@@ -500,6 +525,15 @@ class SessionManager:
500
 
501
  # Start session monitoring
502
  asyncio.create_task(self.monitor_active_session(session_id))
 
 
 
 
 
 
 
 
 
503
 
504
  async def notify_session_start(self, session: UserSession):
505
  """Notify user that their session is starting"""
 
388
  return None
389
 
390
  async def add_session_to_queue(self, session: UserSession):
391
+ """Add a session to the queue"""
 
 
 
392
  self.sessions[session.session_id] = session
393
  self.session_queue.append(session.session_id)
394
  session.status = SessionStatus.QUEUED
395
  session.queue_start_time = time.time()
396
  logger.info(f"Added session {session.session_id} to queue. Queue size: {len(self.session_queue)}")
397
 
398
+ # Don't apply time limits here - wait until after processing queue
399
+ # to see if users actually have to wait
 
400
 
401
  async def apply_queue_limits_to_existing_sessions(self):
402
  """Apply 60-second time limits to existing unlimited sessions when queue forms"""
 
416
  # Notify the user about the new time limit
417
  try:
418
  queue_size = len(self.session_queue)
 
419
 
420
  await session.websocket.send_json({
421
  "type": "queue_limit_applied",
 
422
  "time_remaining": 60.0,
423
  "queue_size": queue_size
424
  })
 
429
  if affected_sessions > 0:
430
  analytics.log_queue_limits_applied(affected_sessions, len(self.session_queue))
431
 
432
+ async def remove_time_limits_if_queue_empty(self):
433
+ """Remove time limits from active sessions when queue becomes empty"""
434
+ if len(self.session_queue) > 0:
435
+ return # Queue not empty, don't remove limits
436
+
437
+ removed_limits = 0
438
+ for session_id in list(self.active_sessions.keys()):
439
+ session = self.sessions.get(session_id)
440
+ if session and session.max_session_time is not None:
441
+ # Remove time limit
442
+ session.max_session_time = None
443
+ session.session_limit_start_time = None
444
+ session.session_warning_sent = False
445
+ removed_limits += 1
446
+
447
+ # Notify user that time limit was removed
448
+ try:
449
+ await session.websocket.send_json({
450
+ "type": "time_limit_removed",
451
+ "reason": "queue_empty"
452
+ })
453
+ logger.info(f"Time limit removed from active session {session_id} (queue empty)")
454
+ except Exception as e:
455
+ logger.error(f"Failed to notify session {session_id} about time limit removal: {e}")
456
+
457
+ if removed_limits > 0:
458
+ logger.info(f"Removed time limits from {removed_limits} active sessions (queue became empty)")
459
+
460
  async def process_queue(self):
461
  """Process the session queue"""
462
+ # Track if we had any existing active sessions before processing
463
+ had_active_sessions = len(self.active_sessions) > 0
464
+
465
  while self.session_queue:
466
  session_id = self.session_queue[0]
467
  session = self.sessions.get(session_id)
 
487
  session.worker_id = worker.worker_id
488
  session.last_activity = time.time()
489
 
490
+ # Set session time limit based on queue status AFTER processing
491
  if len(self.session_queue) > 0:
492
  session.max_session_time = self.MAX_SESSION_TIME_WITH_QUEUE
493
  session.session_limit_start_time = time.time() # Track when limit started
 
525
 
526
  # Start session monitoring
527
  asyncio.create_task(self.monitor_active_session(session_id))
528
+
529
+ # After processing queue, if there are still users waiting AND we had existing active sessions,
530
+ # apply time limits to those existing sessions
531
+ if len(self.session_queue) > 0 and had_active_sessions:
532
+ await self.apply_queue_limits_to_existing_sessions()
533
+
534
+ # If queue became empty and there are active sessions with time limits, remove them
535
+ elif len(self.session_queue) == 0:
536
+ await self.remove_time_limits_if_queue_empty()
537
 
538
  async def notify_session_start(self, session: UserSession):
539
  """Notify user that their session is starting"""
static/index.html CHANGED
@@ -280,29 +280,19 @@
280
  console.log("Server detected user activity, resetting timeout");
281
  stopTimeoutCountdown();
282
  } else if (data.type === "queue_update") {
283
- console.log(`Queue update: Position ${data.position}/${data.total_waiting}, maximum wait: ${data.maximum_wait_seconds.toFixed(1)} seconds`);
284
  const waitSeconds = Math.ceil(data.maximum_wait_seconds);
285
 
286
- let waitText;
287
  if (waitSeconds === 0) {
288
- waitText = "Starting soon...";
289
- } else if (waitSeconds === 1) {
290
- waitText = "1 second max";
291
  } else {
292
- waitText = `${waitSeconds} seconds max`;
293
  }
294
-
295
- const statusText = data.available_workers > 0 ?
296
- "Processing queue..." :
297
- `Position ${data.position} in queue`;
298
-
299
- showConnectionStatus(
300
- statusText,
301
- `Maximum wait: ${waitText} (${data.active_sessions} active sessions)`
302
- );
303
  } else if (data.type === "session_start") {
304
  console.log("Session started, clearing queue display");
305
- // Clear the queue status display
 
306
  ctx.clearRect(0, 0, canvas.width, canvas.height);
307
  } else if (data.type === "session_warning") {
308
  console.log(`Session time warning: ${data.time_remaining} seconds remaining`);
@@ -374,6 +364,11 @@
374
  let timeoutCountdown = 10;
375
  let timeoutWarningActive = false;
376
 
 
 
 
 
 
377
  function startAutoInput() {
378
  if (autoInputInterval) {
379
  clearInterval(autoInputInterval);
@@ -522,6 +517,48 @@
522
  }
523
  }
524
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
525
  function setTimeoutMessage(message) {
526
  const messageElement = document.getElementById('timeoutMessage');
527
  if (messageElement) {
@@ -735,6 +772,7 @@
735
  window.addEventListener('beforeunload', function (e) {
736
  stopAutoInput(); // Clean up auto-input interval
737
  stopTimeoutCountdown(); // Clean up timeout countdown
 
738
  if (isConnected) {
739
  try {
740
  //socket.send(JSON.stringify({ type: "disconnect" }));
 
280
  console.log("Server detected user activity, resetting timeout");
281
  stopTimeoutCountdown();
282
  } else if (data.type === "queue_update") {
283
+ console.log(`Queue update: Position ${data.position}/${data.total_waiting}, wait: ${data.maximum_wait_seconds.toFixed(1)} seconds`);
284
  const waitSeconds = Math.ceil(data.maximum_wait_seconds);
285
 
 
286
  if (waitSeconds === 0) {
287
+ showConnectionStatus("Starting soon...");
288
+ stopQueueCountdown();
 
289
  } else {
290
+ startQueueCountdown(waitSeconds);
291
  }
 
 
 
 
 
 
 
 
 
292
  } else if (data.type === "session_start") {
293
  console.log("Session started, clearing queue display");
294
+ // Stop queue countdown and clear the display
295
+ stopQueueCountdown();
296
  ctx.clearRect(0, 0, canvas.width, canvas.height);
297
  } else if (data.type === "session_warning") {
298
  console.log(`Session time warning: ${data.time_remaining} seconds remaining`);
 
364
  let timeoutCountdown = 10;
365
  let timeoutWarningActive = false;
366
 
367
+ // Queue waiting countdown mechanism
368
+ let queueCountdownInterval = null;
369
+ let queueWaitTime = 0;
370
+ let queueCountdownActive = false;
371
+
372
  function startAutoInput() {
373
  if (autoInputInterval) {
374
  clearInterval(autoInputInterval);
 
517
  }
518
  }
519
 
520
+ function startQueueCountdown(initialWaitTime) {
521
+ if (queueCountdownInterval) {
522
+ clearInterval(queueCountdownInterval);
523
+ }
524
+
525
+ queueWaitTime = initialWaitTime;
526
+ queueCountdownActive = true;
527
+
528
+ // Show initial countdown
529
+ updateQueueCountdownDisplay();
530
+
531
+ // Start countdown
532
+ queueCountdownInterval = setInterval(() => {
533
+ queueWaitTime--;
534
+ updateQueueCountdownDisplay();
535
+
536
+ if (queueWaitTime <= 0) {
537
+ stopQueueCountdown();
538
+ showConnectionStatus("Starting soon...");
539
+ }
540
+ }, 1000);
541
+ }
542
+
543
+ function stopQueueCountdown() {
544
+ if (queueCountdownInterval) {
545
+ clearInterval(queueCountdownInterval);
546
+ queueCountdownInterval = null;
547
+ }
548
+ queueCountdownActive = false;
549
+ queueWaitTime = 0;
550
+ }
551
+
552
+ function updateQueueCountdownDisplay() {
553
+ if (queueWaitTime <= 0) {
554
+ showConnectionStatus("Starting soon...");
555
+ } else if (queueWaitTime === 1) {
556
+ showConnectionStatus("Estimated wait: 1 second");
557
+ } else {
558
+ showConnectionStatus(`Estimated wait: ${queueWaitTime} seconds`);
559
+ }
560
+ }
561
+
562
  function setTimeoutMessage(message) {
563
  const messageElement = document.getElementById('timeoutMessage');
564
  if (messageElement) {
 
772
  window.addEventListener('beforeunload', function (e) {
773
  stopAutoInput(); // Clean up auto-input interval
774
  stopTimeoutCountdown(); // Clean up timeout countdown
775
+ stopQueueCountdown(); // Clean up queue countdown
776
  if (isConnected) {
777
  try {
778
  //socket.send(JSON.stringify({ type: "disconnect" }));