mirror of
https://github.com/HKUDS/nanobot.git
synced 2026-08-10 22:38:40 +03:00
feat(matrix): add configurable graceful sync shutdown
This commit is contained in:
@@ -49,9 +49,28 @@ class MatrixChannel(BaseChannel):
|
|||||||
self._sync_task = asyncio.create_task(self._sync_loop())
|
self._sync_task = asyncio.create_task(self._sync_loop())
|
||||||
|
|
||||||
async def stop(self) -> None:
|
async def stop(self) -> None:
|
||||||
|
"""Stop the Matrix channel with graceful sync shutdown."""
|
||||||
self._running = False
|
self._running = False
|
||||||
|
|
||||||
|
if self.client:
|
||||||
|
# Request sync_forever loop to exit cleanly.
|
||||||
|
self.client.stop_sync_forever()
|
||||||
|
|
||||||
if self._sync_task:
|
if self._sync_task:
|
||||||
self._sync_task.cancel()
|
try:
|
||||||
|
await asyncio.wait_for(
|
||||||
|
asyncio.shield(self._sync_task),
|
||||||
|
timeout=self.config.sync_stop_grace_seconds,
|
||||||
|
)
|
||||||
|
except asyncio.TimeoutError:
|
||||||
|
self._sync_task.cancel()
|
||||||
|
try:
|
||||||
|
await self._sync_task
|
||||||
|
except asyncio.CancelledError:
|
||||||
|
pass
|
||||||
|
except asyncio.CancelledError:
|
||||||
|
pass
|
||||||
|
|
||||||
if self.client:
|
if self.client:
|
||||||
await self.client.close()
|
await self.client.close()
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
"""Configuration schema using Pydantic."""
|
"""Configuration schema using Pydantic."""
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from pydantic import BaseModel, Field
|
from pydantic import BaseModel, Field
|
||||||
from pydantic_settings import BaseSettings
|
from pydantic_settings import BaseSettings
|
||||||
|
|
||||||
@@ -53,6 +54,8 @@ class MatrixConfig(BaseModel):
|
|||||||
access_token: str = ""
|
access_token: str = ""
|
||||||
user_id: str = "" # @bot:matrix.org
|
user_id: str = "" # @bot:matrix.org
|
||||||
device_id: str = ""
|
device_id: str = ""
|
||||||
|
# Max seconds to wait for sync_forever to stop gracefully before cancellation fallback.
|
||||||
|
sync_stop_grace_seconds: int = 2
|
||||||
allow_from: list[str] = Field(default_factory=list)
|
allow_from: list[str] = Field(default_factory=list)
|
||||||
|
|
||||||
class ChannelsConfig(BaseModel):
|
class ChannelsConfig(BaseModel):
|
||||||
@@ -137,12 +140,12 @@ class Config(BaseSettings):
|
|||||||
providers: ProvidersConfig = Field(default_factory=ProvidersConfig)
|
providers: ProvidersConfig = Field(default_factory=ProvidersConfig)
|
||||||
gateway: GatewayConfig = Field(default_factory=GatewayConfig)
|
gateway: GatewayConfig = Field(default_factory=GatewayConfig)
|
||||||
tools: ToolsConfig = Field(default_factory=ToolsConfig)
|
tools: ToolsConfig = Field(default_factory=ToolsConfig)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def workspace_path(self) -> Path:
|
def workspace_path(self) -> Path:
|
||||||
"""Get expanded workspace path."""
|
"""Get expanded workspace path."""
|
||||||
return Path(self.agents.defaults.workspace).expanduser()
|
return Path(self.agents.defaults.workspace).expanduser()
|
||||||
|
|
||||||
def _match_provider(self, model: str | None = None) -> tuple["ProviderConfig | None", str | None]:
|
def _match_provider(self, model: str | None = None) -> tuple["ProviderConfig | None", str | None]:
|
||||||
"""Match provider config and its registry name. Returns (config, spec_name)."""
|
"""Match provider config and its registry name. Returns (config, spec_name)."""
|
||||||
from nanobot.providers.registry import PROVIDERS
|
from nanobot.providers.registry import PROVIDERS
|
||||||
@@ -175,7 +178,7 @@ class Config(BaseSettings):
|
|||||||
"""Get API key for the given model. Falls back to first available key."""
|
"""Get API key for the given model. Falls back to first available key."""
|
||||||
p = self.get_provider(model)
|
p = self.get_provider(model)
|
||||||
return p.api_key if p else None
|
return p.api_key if p else None
|
||||||
|
|
||||||
def get_api_base(self, model: str | None = None) -> str | None:
|
def get_api_base(self, model: str | None = None) -> str | None:
|
||||||
"""Get API base URL for the given model. Applies default URLs for known gateways."""
|
"""Get API base URL for the given model. Applies default URLs for known gateways."""
|
||||||
from nanobot.providers.registry import find_by_name
|
from nanobot.providers.registry import find_by_name
|
||||||
@@ -190,7 +193,7 @@ class Config(BaseSettings):
|
|||||||
if spec and spec.is_gateway and spec.default_api_base:
|
if spec and spec.is_gateway and spec.default_api_base:
|
||||||
return spec.default_api_base
|
return spec.default_api_base
|
||||||
return None
|
return None
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
env_prefix = "NANOBOT_"
|
env_prefix = "NANOBOT_"
|
||||||
env_nested_delimiter = "__"
|
env_nested_delimiter = "__"
|
||||||
|
|||||||
Reference in New Issue
Block a user