distinguish the timeout failure which should mark the is_session_completed true - #55
Conversation
📝 WalkthroughWalkthroughChangesSession completion modes
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant SimulationWorker
participant GatewayClient
participant GatewayApp
participant GatewayTelemetry
participant GatewayStorage
participant StorageStrategy
SimulationWorker->>SimulationWorker: classify rollout result
SimulationWorker->>GatewayClient: close session with completion_mode
GatewayClient->>GatewayApp: send close request
GatewayApp->>GatewayTelemetry: enqueue completion status
GatewayApp->>GatewayStorage: record session close
GatewayStorage->>StorageStrategy: update latest session completion state
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@core/data_manager/strategy/sqlite_strategy_impl.py`:
- Around line 537-544: Update the incomplete-session branch in the session
completion flow around the latest-row update so that when completed is false,
rewards and step rewards are cleared for every trajectory row belonging to the
same session and model, not only latest.id. Preserve the existing latest-row
completion and terminal flags, and ensure fetch_done_steps_with_context cannot
return earlier trainable rows from an aborted session.
In `@manager/simulation_worker.py`:
- Around line 499-514: Update _gateway_completion_mode to evaluate recognized
timeout_layer values before checking metrics["rjob_status"], so
rjob_wait_terminal and the other timeout layers return "complete" even when
rjob_status is "Stopped", "Failed", or "Killed". Preserve the existing
truncated, succeeded, and abort behavior for results without a recognized
timeout layer.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 7347847d-79b9-4e0d-9b0e-a9769851aff4
📒 Files selected for processing (10)
core/data_manager/manager.pycore/data_manager/strategy/base_strategy.pycore/data_manager/strategy/cloud_strategy_impl.pycore/data_manager/strategy/sqlite_strategy_impl.pyevaluator/gateway_client.pygateway/app.pygateway/storage.pygateway/telemetry.pymanager/rjob_episode_runner.pymanager/simulation_worker.py
| updates: Dict[str, Any] = { | ||
| "is_session_completed": completed, | ||
| "is_terminal": completed, | ||
| } | ||
| if not completed: | ||
| updates.update(step_reward=0.0, reward=0.0) | ||
| with trace.span("db_write.mark_session_completed", row_id=latest.id, step_id=latest.step_id): | ||
| updated = await SessionStep.filter(id=latest.id).update( | ||
| is_session_completed=True, | ||
| is_terminal=True, | ||
| ) | ||
| updated = await SessionStep.filter(id=latest.id).update(**updates) |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift
Clear rewards for all aborted trajectory rows.
When an aborted session has more than one trainable row, this update clears rewards only on the latest row. fetch_done_steps_with_context still returns earlier trainable rows without checking completion state. Those rows can enter training with rewards from an aborted session.
Update all trajectory rows for the session and model when completed is false. Alternatively, exclude incomplete sessions in fetch_done_steps_with_context.
Proposed fix
- with trace.span("db_write.mark_session_completed", row_id=latest.id, step_id=latest.step_id):
- updated = await SessionStep.filter(id=latest.id).update(**updates)
+ target = SessionStep.filter(session_id=session_id)
+ if llm_model:
+ target = target.filter(llm_model=llm_model)
+ with trace.span("db_write.mark_session_completed", row_id=latest.id, step_id=latest.step_id):
+ updated = await target.update(**updates)📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| updates: Dict[str, Any] = { | |
| "is_session_completed": completed, | |
| "is_terminal": completed, | |
| } | |
| if not completed: | |
| updates.update(step_reward=0.0, reward=0.0) | |
| with trace.span("db_write.mark_session_completed", row_id=latest.id, step_id=latest.step_id): | |
| updated = await SessionStep.filter(id=latest.id).update( | |
| is_session_completed=True, | |
| is_terminal=True, | |
| ) | |
| updated = await SessionStep.filter(id=latest.id).update(**updates) | |
| updates: Dict[str, Any] = { | |
| "is_session_completed": completed, | |
| "is_terminal": completed, | |
| } | |
| if not completed: | |
| updates.update(step_reward=0.0, reward=0.0) | |
| target = SessionStep.filter(session_id=session_id) | |
| if llm_model: | |
| target = target.filter(llm_model=llm_model) | |
| with trace.span("db_write.mark_session_completed", row_id=latest.id, step_id=latest.step_id): | |
| updated = await target.update(**updates) |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@core/data_manager/strategy/sqlite_strategy_impl.py` around lines 537 - 544,
Update the incomplete-session branch in the session completion flow around the
latest-row update so that when completed is false, rewards and step rewards are
cleared for every trajectory row belonging to the same session and model, not
only latest.id. Preserve the existing latest-row completion and terminal flags,
and ensure fetch_done_steps_with_context cannot return earlier trainable rows
from an aborted session.
| @staticmethod | ||
| def _gateway_completion_mode(result: SimulationStartResult) -> str: | ||
| metrics = result.metrics if isinstance(result.metrics, dict) else {} | ||
| if str(metrics.get("rjob_status") or "") in {"Failed", "Stopped", "Killed"}: | ||
| return "abort" | ||
| if result.truncated: | ||
| return "complete" | ||
| if str(metrics.get("timeout_layer") or "") in { | ||
| "docker_exec", | ||
| "sandbox_command", | ||
| "rjob_wait_terminal", | ||
| }: | ||
| return "complete" | ||
| if result.status == "succeeded": | ||
| return "complete" | ||
| return "abort" |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Prioritize timeout-layer classification.
If TimeoutError.last_status is "Stopped", RJobEpisodeRunner stores that value in metrics["rjob_status"]. This method then returns "abort" before it checks timeout_layer="rjob_wait_terminal". The gateway marks that timeout session incomplete and clears its reward.
Check recognized timeout layers before rjob_status.
Proposed fix
def _gateway_completion_mode(result: SimulationStartResult) -> str:
metrics = result.metrics if isinstance(result.metrics, dict) else {}
- if str(metrics.get("rjob_status") or "") in {"Failed", "Stopped", "Killed"}:
- return "abort"
if result.truncated:
return "complete"
if str(metrics.get("timeout_layer") or "") in {
"docker_exec",
"sandbox_command",
"rjob_wait_terminal",
}:
return "complete"
+ if str(metrics.get("rjob_status") or "") in {"Failed", "Stopped", "Killed"}:
+ return "abort"
if result.status == "succeeded":
return "complete"
return "abort"📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| @staticmethod | |
| def _gateway_completion_mode(result: SimulationStartResult) -> str: | |
| metrics = result.metrics if isinstance(result.metrics, dict) else {} | |
| if str(metrics.get("rjob_status") or "") in {"Failed", "Stopped", "Killed"}: | |
| return "abort" | |
| if result.truncated: | |
| return "complete" | |
| if str(metrics.get("timeout_layer") or "") in { | |
| "docker_exec", | |
| "sandbox_command", | |
| "rjob_wait_terminal", | |
| }: | |
| return "complete" | |
| if result.status == "succeeded": | |
| return "complete" | |
| return "abort" | |
| `@staticmethod` | |
| def _gateway_completion_mode(result: SimulationStartResult) -> str: | |
| metrics = result.metrics if isinstance(result.metrics, dict) else {} | |
| if result.truncated: | |
| return "complete" | |
| if str(metrics.get("timeout_layer") or "") in { | |
| "docker_exec", | |
| "sandbox_command", | |
| "rjob_wait_terminal", | |
| }: | |
| return "complete" | |
| if str(metrics.get("rjob_status") or "") in {"Failed", "Stopped", "Killed"}: | |
| return "abort" | |
| if result.status == "succeeded": | |
| return "complete" | |
| return "abort" |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@manager/simulation_worker.py` around lines 499 - 514, Update
_gateway_completion_mode to evaluate recognized timeout_layer values before
checking metrics["rjob_status"], so rjob_wait_terminal and the other timeout
layers return "complete" even when rjob_status is "Stopped", "Failed", or
"Killed". Preserve the existing truncated, succeeded, and abort behavior for
results without a recognized timeout layer.
Summary by CodeRabbit
New Features
Bug Fixes