66from pathlib import Path
77from typing import Any , Optional
88
9+ import aiohttp
10+ import gql
11+ import gql .transport .exceptions
912import jsonschema
10- from pymongo .errors import PyMongoError
13+
14+ from flexus_client_kit import ckit_client
1115
1216logger = logging .getLogger (__name__ )
1317
18+ _GQL_DISABLED_RULES = gql .gql (
19+ """query AutomationDisabledRulesRuntime($persona_id: String!) {
20+ automation_disabled_rules(persona_id: $persona_id)
21+ }"""
22+ )
23+
1424# Loaded by set_automation_schema_dict() from ckit_automation_v1_schema_build (authoritative) or
1525# set_automation_schema(path) for tests / offline fixtures.
1626_AUTOMATION_SCHEMA : dict | None = None
@@ -113,8 +123,18 @@ def validate_automation_json(data: dict) -> list[str]:
113123
114124
115125class DisabledRulesCache :
116- def __init__ (self , mongo_db : Any , interval : float = 30.0 ):
117- self ._mongo_db = mongo_db
126+ """
127+ In-memory cache of disabled automation rule IDs for a persona, refreshed periodically
128+ from the backend GraphQL automation_disabled_rules endpoint.
129+
130+ Polling at 5 s so that rule enable/disable toggles made in the UI propagate to the
131+ runtime within a few seconds without requiring a bot restart. The GQL query is cheap
132+ (returns only a list of IDs), so the extra request frequency is negligible.
133+ """
134+
135+ def __init__ (self , fclient : ckit_client .FlexusClient , persona_id : str , interval : float = 5.0 ):
136+ self ._fclient = fclient
137+ self ._persona_id = persona_id
118138 self ._interval = interval
119139 self ._disabled : set = set ()
120140 self ._task : Optional [asyncio .Task ] = None
@@ -136,15 +156,19 @@ def get(self) -> set:
136156
137157 async def _refresh (self ) -> None :
138158 try :
139- doc = await self ._mongo_db ["bot_runtime_config" ].find_one ({"_id" : "disabled_rule_ids" })
140- if doc and isinstance (doc .get ("ids" ), list ):
141- self ._disabled = {str (x ) for x in doc ["ids" ] if x }
142- else :
143- self ._disabled = set ()
144- except PyMongoError as e :
145- logger .warning ("DisabledRulesCache refresh failed (mongo), keeping last known state: %s %s" , type (e ).__name__ , e )
146- except (TypeError , ValueError ) as e :
147- logger .warning ("DisabledRulesCache refresh failed (bad doc), keeping last known state: %s %s" , type (e ).__name__ , e )
159+ async with (await self ._fclient .use_http_on_behalf (self ._persona_id , "" )) as http :
160+ result = await http .execute (
161+ _GQL_DISABLED_RULES ,
162+ variable_values = {"persona_id" : self ._persona_id },
163+ )
164+ ids = result .get ("automation_disabled_rules" ) or []
165+ self ._disabled = {str (x ) for x in ids if x }
166+ except gql .transport .exceptions .TransportError as e :
167+ logger .warning ("DisabledRulesCache refresh failed (backend), keeping last known state: %s %s" , type (e ).__name__ , e )
168+ except aiohttp .ClientError as e :
169+ logger .warning ("DisabledRulesCache refresh failed (network), keeping last known state: %s %s" , type (e ).__name__ , e )
170+ except (TypeError , ValueError , KeyError ) as e :
171+ logger .warning ("DisabledRulesCache refresh failed (bad response), keeping last known state: %s %s" , type (e ).__name__ , e )
148172
149173 async def _loop (self ) -> None :
150174 while True :
0 commit comments