Spaces:
Sleeping
Sleeping
Claude Code Claude Opus 4.6 commited on
Commit ·
45a307e
1
Parent(s): 7aac46e
Claude Code: Add verbose startup logging for asyncio task debugging
Browse files- Add detailed logging in startup_event to prove handler ran
- Wrap asyncio.create_task in try/except to catch failures
- Add log before while True loop to verify task entry
- Add iteration logging in polling loop
- Reduce sleep to 1s for faster feedback
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
app.py
CHANGED
|
@@ -87,9 +87,17 @@ async def _poll_a2a_ready_state():
|
|
| 87 |
Background polling task to detect RUNNING_A2A_READY state and trigger agent execution.
|
| 88 |
This bridges the synchronization deadlock where the worker ignores push events.
|
| 89 |
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 90 |
data_dir = Path(os.environ.get("OPENCLAW_DATA_DIR", "/data"))
|
| 91 |
status_file = data_dir / "cain_status.json"
|
| 92 |
|
|
|
|
| 93 |
while True:
|
| 94 |
try:
|
| 95 |
# Read current status
|
|
@@ -114,12 +122,14 @@ async def _poll_a2a_ready_state():
|
|
| 114 |
except Exception as e:
|
| 115 |
logger.warning(f"[A2A Polling] Failed to trigger agent: {e}")
|
| 116 |
|
| 117 |
-
#
|
| 118 |
-
|
|
|
|
|
|
|
| 119 |
|
| 120 |
except Exception as e:
|
| 121 |
logger.warning(f"[A2A Polling] Error in polling loop: {e}")
|
| 122 |
-
await asyncio.sleep(
|
| 123 |
|
| 124 |
|
| 125 |
@app.on_event("startup")
|
|
@@ -127,6 +137,13 @@ async def startup_event():
|
|
| 127 |
"""Start background worker thread and A2A polling task on app startup."""
|
| 128 |
global _worker_thread, _worker_stop_event, _polling_task
|
| 129 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 130 |
# Check WORKER_MODE before starting worker
|
| 131 |
worker_mode = os.environ.get("WORKER_MODE", "auto").lower()
|
| 132 |
if worker_mode == "disabled":
|
|
@@ -138,8 +155,18 @@ async def startup_event():
|
|
| 138 |
_worker_thread.start()
|
| 139 |
logger.info(f"[Cain] Worker thread started: {_worker_thread.name}")
|
| 140 |
|
| 141 |
-
|
| 142 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 143 |
|
| 144 |
|
| 145 |
@app.on_event("shutdown")
|
|
|
|
| 87 |
Background polling task to detect RUNNING_A2A_READY state and trigger agent execution.
|
| 88 |
This bridges the synchronization deadlock where the worker ignores push events.
|
| 89 |
"""
|
| 90 |
+
# 3. Hard loop check - log BEFORE entering while loop
|
| 91 |
+
logger.info("=" * 60)
|
| 92 |
+
logger.info("[POLLING TASK] ========== _poll_a2a_ready_state() ENTERED ==========")
|
| 93 |
+
logger.info(f"[POLLING TASK] Timestamp: {datetime.utcnow().isoformat()}")
|
| 94 |
+
logger.info("[POLLING TASK] About to enter while True loop...")
|
| 95 |
+
logger.info("=" * 60)
|
| 96 |
+
|
| 97 |
data_dir = Path(os.environ.get("OPENCLAW_DATA_DIR", "/data"))
|
| 98 |
status_file = data_dir / "cain_status.json"
|
| 99 |
|
| 100 |
+
iteration = 0
|
| 101 |
while True:
|
| 102 |
try:
|
| 103 |
# Read current status
|
|
|
|
| 122 |
except Exception as e:
|
| 123 |
logger.warning(f"[A2A Polling] Failed to trigger agent: {e}")
|
| 124 |
|
| 125 |
+
# 4. Timeout safety - sleep with iteration logging
|
| 126 |
+
iteration += 1
|
| 127 |
+
logger.info(f"[POLLING TASK] Iteration {iteration} complete, sleeping 1s...")
|
| 128 |
+
await asyncio.sleep(1) # Reduced to 1s for faster feedback
|
| 129 |
|
| 130 |
except Exception as e:
|
| 131 |
logger.warning(f"[A2A Polling] Error in polling loop: {e}")
|
| 132 |
+
await asyncio.sleep(1)
|
| 133 |
|
| 134 |
|
| 135 |
@app.on_event("startup")
|
|
|
|
| 137 |
"""Start background worker thread and A2A polling task on app startup."""
|
| 138 |
global _worker_thread, _worker_stop_event, _polling_task
|
| 139 |
|
| 140 |
+
# 1. Verbose startup logging - prove handler ran
|
| 141 |
+
logger.info("=" * 60)
|
| 142 |
+
logger.info("[STARTUP] ========== STARTUP EVENT HANDLER TRIGGERED ==========")
|
| 143 |
+
logger.info(f"[STARTUP] Timestamp: {datetime.utcnow().isoformat()}")
|
| 144 |
+
logger.info(f"[STARTUP] PID: {os.getpid()}")
|
| 145 |
+
logger.info("=" * 60)
|
| 146 |
+
|
| 147 |
# Check WORKER_MODE before starting worker
|
| 148 |
worker_mode = os.environ.get("WORKER_MODE", "auto").lower()
|
| 149 |
if worker_mode == "disabled":
|
|
|
|
| 155 |
_worker_thread.start()
|
| 156 |
logger.info(f"[Cain] Worker thread started: {_worker_thread.name}")
|
| 157 |
|
| 158 |
+
# 2. Wrap task creation in try/except
|
| 159 |
+
logger.info("[STARTUP] About to create asyncio task for A2A polling...")
|
| 160 |
+
try:
|
| 161 |
+
_polling_task = asyncio.create_task(_poll_a2a_ready_state())
|
| 162 |
+
logger.info(f"[STARTUP] SUCCESS: asyncio.create_task() returned task object: {_polling_task}")
|
| 163 |
+
logger.info(f"[STARTUP] Task done? {_polling_task.done()}")
|
| 164 |
+
logger.info(f"[STARTUP] Task cancelled? {_polling_task.cancelled()}")
|
| 165 |
+
except Exception as e:
|
| 166 |
+
logger.error(f"[STARTUP] FAILED: asyncio.create_task() raised exception: {e}")
|
| 167 |
+
import traceback
|
| 168 |
+
traceback.print_exc()
|
| 169 |
+
_polling_task = None
|
| 170 |
|
| 171 |
|
| 172 |
@app.on_event("shutdown")
|