Add manual retry flow for failed meeting summaries
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
import asyncio
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from types import SimpleNamespace
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(__file__)))
|
||||
|
||||
import discord
|
||||
|
||||
import bot
|
||||
|
||||
|
||||
class FakeChannel:
|
||||
def __init__(self, failures_before_success=0, channel_id=999):
|
||||
self.failures_before_success = failures_before_success
|
||||
self.messages = []
|
||||
self.attempts = 0
|
||||
self.id = channel_id
|
||||
|
||||
async def send(self, text):
|
||||
self.attempts += 1
|
||||
if self.attempts <= self.failures_before_success:
|
||||
response = SimpleNamespace(status=403, reason="Forbidden")
|
||||
raise discord.Forbidden(response, {"message": "Missing Permissions", "code": 50013})
|
||||
self.messages.append(text)
|
||||
|
||||
|
||||
def test_safe_send_chunked_falls_back_to_secondary_channel():
|
||||
async def run():
|
||||
primary = FakeChannel(failures_before_success=1, channel_id=100)
|
||||
fallback = FakeChannel(channel_id=200)
|
||||
delivered = await bot.safe_send_chunked(
|
||||
primary,
|
||||
"hello world",
|
||||
fallback_channels=[fallback],
|
||||
purpose="test notification",
|
||||
)
|
||||
return delivered, fallback.messages
|
||||
|
||||
delivered, messages = asyncio.run(run())
|
||||
assert messages == ["hello world"]
|
||||
assert delivered is not None
|
||||
|
||||
|
||||
def test_safe_send_chunked_returns_none_when_all_channels_fail():
|
||||
async def run():
|
||||
primary = FakeChannel(failures_before_success=10, channel_id=100)
|
||||
fallback = FakeChannel(failures_before_success=10, channel_id=200)
|
||||
return await bot.safe_send_chunked(
|
||||
primary,
|
||||
"hello world",
|
||||
fallback_channels=[fallback],
|
||||
purpose="test notification",
|
||||
)
|
||||
|
||||
assert asyncio.run(run()) is None
|
||||
|
||||
|
||||
def test_build_retry_notice_mentions_reason_and_path():
|
||||
message = bot.build_retry_notice(
|
||||
file_path=str(Path("recordings") / "1" / "session" / "meeting.wav"),
|
||||
reason="OpenRouter 502",
|
||||
)
|
||||
|
||||
assert "OpenRouter 502" in message
|
||||
assert "meeting.wav" in message
|
||||
assert "`/retry`" in message
|
||||
@@ -0,0 +1,41 @@
|
||||
import asyncio
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(__file__)))
|
||||
|
||||
import config
|
||||
|
||||
|
||||
def _reset_config_path(tmp_path: Path):
|
||||
config.CONFIG_PATH = tmp_path / "config.json"
|
||||
|
||||
|
||||
def test_retry_state_round_trip(tmp_path):
|
||||
async def run():
|
||||
_reset_config_path(tmp_path)
|
||||
await config.set_retry_state(
|
||||
guild_id=123,
|
||||
file_path="recordings/123/session/meeting.wav",
|
||||
source_channel_id=456,
|
||||
reason="transcription failed",
|
||||
)
|
||||
return await config.get_retry_state(123)
|
||||
|
||||
state = asyncio.run(run())
|
||||
assert state == {
|
||||
"file_path": "recordings/123/session/meeting.wav",
|
||||
"source_channel_id": 456,
|
||||
"reason": "transcription failed",
|
||||
}
|
||||
|
||||
|
||||
def test_clear_retry_state_removes_saved_entry(tmp_path):
|
||||
async def run():
|
||||
_reset_config_path(tmp_path)
|
||||
await config.set_retry_state(123, "a.wav", 456, "oops")
|
||||
await config.clear_retry_state(123)
|
||||
return await config.get_retry_state(123)
|
||||
|
||||
assert asyncio.run(run()) is None
|
||||
Reference in New Issue
Block a user