|
35 | 35 | import atexit |
36 | 36 | import hashlib |
37 | 37 | import json |
| 38 | +from functools import wraps |
38 | 39 | from datetime import datetime, timezone |
39 | 40 | from pathlib import Path |
40 | | -from typing import Optional, Dict, Any, Mapping, Sequence |
| 41 | +from typing import Optional, Dict, Any, Callable, Mapping, Sequence |
41 | 42 |
|
42 | 43 | # Load environment variables for DAEs (API keys, ports, feature flags). |
43 | 44 | # Managed mode builds `.env.managed` from `.env` (last duplicate wins) for |
@@ -3904,8 +3905,7 @@ def _reddog_queue_stage_rejection_reasons(stage_callable: Any) -> tuple[str, ... |
3904 | 3905 |
|
3905 | 3906 | def _reddog_record_queue_control_result(repo_root: Path, result: Mapping[str, Any]) -> Dict[str, Any]: |
3906 | 3907 | """Record and expose one resident queue control-loop result.""" |
3907 | | - |
3908 | | - recorded = dict(result) |
| 3908 | + recorded = _reddog_control_lock_annotated_result(result) |
3909 | 3909 | try: |
3910 | 3910 | from modules.communication.moltbot_bridge.src.reddog_resident_queue_binding_profile import ( |
3911 | 3911 | resident_queue_runtime_file_path, |
@@ -3955,6 +3955,49 @@ def _reddog_record_queue_control_result(repo_root: Path, result: Mapping[str, An |
3955 | 3955 | return recorded |
3956 | 3956 |
|
3957 | 3957 |
|
| 3958 | +def _reddog_control_lock_annotated_result(result: Mapping[str, Any]) -> Dict[str, Any]: |
| 3959 | + from modules.communication.moltbot_bridge.src.reddog_resident_queue_control_lock import ( |
| 3960 | + resident_queue_control_lock_held, |
| 3961 | + ) |
| 3962 | + |
| 3963 | + recorded = dict(result) |
| 3964 | + recorded["control_lock_acquired"] = resident_queue_control_lock_held() |
| 3965 | + return recorded |
| 3966 | + |
| 3967 | + |
| 3968 | +def _with_reddog_queue_control_lock(control_loop: Callable[[Path], bool]) -> Callable[[Path], bool]: |
| 3969 | + """Decorate every control-loop call with the shared non-blocking lock.""" |
| 3970 | + |
| 3971 | + @wraps(control_loop) |
| 3972 | + def locked(repo_root: Path) -> bool: |
| 3973 | + from modules.communication.moltbot_bridge.src.reddog_resident_queue_control_lock import ( |
| 3974 | + acquire_resident_queue_control_lock, |
| 3975 | + ) |
| 3976 | + |
| 3977 | + with acquire_resident_queue_control_lock(repo_root) as lock: |
| 3978 | + if not lock.acquired: |
| 3979 | + locked.last_result = _reddog_locked_control_result(lock.reason, lock.path) |
| 3980 | + return False |
| 3981 | + return control_loop(repo_root) |
| 3982 | + |
| 3983 | + return locked |
| 3984 | + |
| 3985 | + |
| 3986 | +def _reddog_locked_control_result(reason: str, lock_path: Path) -> Dict[str, Any]: |
| 3987 | + return { |
| 3988 | + "accepted": False, |
| 3989 | + "status": "CONTROL_LOOP_LOCKED", |
| 3990 | + "rounds": 0, |
| 3991 | + "serial_progress": 0, |
| 3992 | + "claim_progress": 0, |
| 3993 | + "receipt_ids": (), |
| 3994 | + "rejection_reasons": (reason,), |
| 3995 | + "control_lock_path": str(lock_path), |
| 3996 | + "control_lock_acquired": False, |
| 3997 | + } |
| 3998 | + |
| 3999 | + |
| 4000 | +@_with_reddog_queue_control_lock |
3958 | 4001 | def run_reddog_resident_queue_control_loop_preflight(repo_root: Path) -> bool: |
3959 | 4002 | """ |
3960 | 4003 | Drive the resident queue through bounded serial/claim rounds. |
|
0 commit comments