mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-06-12 02:15:58 +00:00
Ensure runtime IM channels are ready after restart
This commit is contained in:
@@ -247,6 +247,60 @@ def test_get_providers_reports_configured_channel_not_running(tmp_path, monkeypa
|
||||
anyio.run(repo.close)
|
||||
|
||||
|
||||
def test_get_providers_restarts_configured_channel_when_service_can_reconcile(tmp_path, monkeypatch):
|
||||
import anyio
|
||||
|
||||
repo = anyio.run(_make_repo, tmp_path)
|
||||
config = ChannelConnectionsConfig.model_validate(
|
||||
{
|
||||
"enabled": True,
|
||||
"feishu": {"enabled": True},
|
||||
}
|
||||
)
|
||||
channels_config = {
|
||||
"feishu": {
|
||||
"enabled": True,
|
||||
"app_id": "feishu-app",
|
||||
"app_secret": "feishu-secret",
|
||||
}
|
||||
}
|
||||
app = _make_app(config, repo, channels_config)
|
||||
status = {
|
||||
"service_running": True,
|
||||
"channels": {
|
||||
"feishu": {
|
||||
"enabled": True,
|
||||
"running": False,
|
||||
}
|
||||
},
|
||||
}
|
||||
reconciled: list[tuple[str, dict]] = []
|
||||
|
||||
async def ensure_channel_ready(provider, runtime_config):
|
||||
reconciled.append((provider, dict(runtime_config)))
|
||||
status["channels"][provider]["running"] = True
|
||||
return True
|
||||
|
||||
service = SimpleNamespace(
|
||||
get_status=lambda: status,
|
||||
ensure_channel_ready=ensure_channel_ready,
|
||||
)
|
||||
monkeypatch.setattr("app.channels.service.get_channel_service", lambda: service)
|
||||
|
||||
with TestClient(app) as client:
|
||||
response = client.get("/api/channels/providers")
|
||||
|
||||
assert response.status_code == 200
|
||||
by_provider = {item["provider"]: item for item in response.json()["providers"]}
|
||||
assert by_provider["feishu"]["configured"] is True
|
||||
assert by_provider["feishu"]["connectable"] is True
|
||||
assert by_provider["feishu"]["connection_status"] == "connected"
|
||||
assert by_provider["feishu"]["unavailable_reason"] is None
|
||||
assert reconciled == [("feishu", channels_config["feishu"])]
|
||||
|
||||
anyio.run(repo.close)
|
||||
|
||||
|
||||
def test_get_providers_uses_newest_connection_status_per_provider(tmp_path):
|
||||
import anyio
|
||||
|
||||
|
||||
@@ -3504,6 +3504,51 @@ class TestChannelService:
|
||||
"app_token": "xapp-ui",
|
||||
}
|
||||
|
||||
def test_start_retries_configured_channel_until_ready(self, monkeypatch):
|
||||
from app.channels.service import ChannelService
|
||||
|
||||
class FlakyReadyChannel(Channel):
|
||||
starts = 0
|
||||
|
||||
def __init__(self, bus, config):
|
||||
super().__init__(name="slack", bus=bus, config=config)
|
||||
|
||||
async def start(self):
|
||||
type(self).starts += 1
|
||||
self._running = type(self).starts >= 2
|
||||
|
||||
async def stop(self):
|
||||
self._running = False
|
||||
|
||||
async def send(self, msg):
|
||||
return None
|
||||
|
||||
monkeypatch.setattr(
|
||||
"deerflow.reflection.resolve_class",
|
||||
lambda import_path, base_class=None: FlakyReadyChannel,
|
||||
)
|
||||
|
||||
async def go():
|
||||
service = ChannelService(
|
||||
channels_config={
|
||||
"slack": {
|
||||
"enabled": True,
|
||||
"bot_token": "xoxb-ui",
|
||||
"app_token": "xapp-ui",
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
try:
|
||||
await service.start()
|
||||
|
||||
assert FlakyReadyChannel.starts == 2
|
||||
assert service.get_status()["channels"]["slack"]["running"] is True
|
||||
finally:
|
||||
await service.stop()
|
||||
|
||||
_run(go())
|
||||
|
||||
def test_connection_repo_is_forwarded_to_manager(self):
|
||||
from app.channels.service import ChannelService
|
||||
|
||||
|
||||
Reference in New Issue
Block a user