diff --git a/src/bespokelabs/curator/request_processor/online/base_online_request_processor.py b/src/bespokelabs/curator/request_processor/online/base_online_request_processor.py index 085c2ec9..7110f476 100644 --- a/src/bespokelabs/curator/request_processor/online/base_online_request_processor.py +++ b/src/bespokelabs/curator/request_processor/online/base_online_request_processor.py @@ -403,6 +403,7 @@ async def process_requests_from_file( status_tracker.num_tasks_started += 1 status_tracker.num_tasks_in_progress += 1 + status_tracker.update_display() if pending_requests: await asyncio.gather(*pending_requests) @@ -561,6 +562,7 @@ async def handle_single_request_with_retries( await self.append_generic_response(status_tracker, generic_response, response_file) status_tracker.num_tasks_in_progress -= 1 status_tracker.num_tasks_failed += 1 + status_tracker.update_display() return else: self._add_output_token_moving_window(generic_response.token_usage.output) diff --git a/src/bespokelabs/curator/status_tracker/online_status_tracker.py b/src/bespokelabs/curator/status_tracker/online_status_tracker.py index 76039450..bb348057 100644 --- a/src/bespokelabs/curator/status_tracker/online_status_tracker.py +++ b/src/bespokelabs/curator/status_tracker/online_status_tracker.py @@ -317,7 +317,7 @@ def update_display(self): # 3. When costs or tokens change should_update = ( current_time - self._last_stats_update >= _STATUS_UPDATE_INTERVAL # Time-based update - and ( + or ( self.num_tasks_in_progress != getattr(self, "_last_in_progress", -1) # Task state change or self.num_tasks_succeeded != getattr(self, "_last_succeeded", -1) or self.num_tasks_failed != getattr(self, "_last_failed", -1) diff --git a/tests/unittests/test_online_status_tracker.py b/tests/unittests/test_online_status_tracker.py index 949f8d48..c6341e21 100644 --- a/tests/unittests/test_online_status_tracker.py +++ b/tests/unittests/test_online_status_tracker.py @@ -42,7 +42,7 @@ def test_online_status_tracker_display(): assert "100" in captured # Total requests assert "50✓" in captured.replace(" ", "") # Success count assert "5✗" in captured.replace(" ", "") # Failed count - assert "10⋯" in captured.replace(" ", "") # In progress count + assert "10⋯" in captured.replace(" ", "") or "10…" in captured.replace(" ", "") # In progress count assert "$0.123" in captured # Cost assert "1000" in captured # Input tokens assert "2000" in captured # Output tokens @@ -120,3 +120,29 @@ def test_online_status_tracker_external_model_cost_missing_keys(): assert tracker.output_cost_per_million is None assert "N/A" in tracker.input_cost_str assert "N/A" in tracker.output_cost_str + + +def test_online_status_tracker_requests_in_progress_update(): + """Test that requests in progress update immediately via update_display.""" + output = StringIO() + console = Console(file=output, width=200, force_terminal=True) + tracker = OnlineStatusTracker() + tracker.model = "test-model" + tracker.total_requests = 10 + tracker.start_tracker(console) + + # Dispatch request: tasks started and in_progress increase + tracker.num_tasks_started += 1 + tracker.num_tasks_in_progress += 1 + tracker.update_display() + + assert tracker.num_tasks_in_progress == 1 + assert tracker.max_concurrent_requests_seen == 1 + + # Task finishes: in_progress decrements, succeeded increments + tracker.num_tasks_in_progress -= 1 + tracker.num_tasks_succeeded += 1 + tracker.update_display() + + assert tracker.num_tasks_in_progress == 0 + tracker.stop_tracker() diff --git a/tests/unittests/test_status_tracker.py b/tests/unittests/test_status_tracker.py index 9d787295..7358fa46 100644 --- a/tests/unittests/test_status_tracker.py +++ b/tests/unittests/test_status_tracker.py @@ -46,7 +46,7 @@ def test_online_status_tracker_display(): assert "test-model" in captured assert "50✓" in captured.replace(" ", "") # Success count assert "5✗" in captured.replace(" ", "") # Failed count - assert "10⋯" in captured.replace(" ", "") # In progress count + assert "10⋯" in captured.replace(" ", "") or "10…" in captured.replace(" ", "") # In progress count assert "$0.123" in captured # Cost assert "1000" in captured # Input tokens assert "2000" in captured # Output tokens