feat: trigger variant card renders after post-game tier-ups
After refractor tier-ups, the bot hits the card render URL for each variant card to trigger Playwright render + S3 upload as a side effect. Fire-and-forget — failures are logged but never raised. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
9ee4a76cd6
commit
730d4b4f60
@ -1,5 +1,6 @@
|
||||
import asyncio
|
||||
import copy
|
||||
import datetime
|
||||
import logging
|
||||
import discord
|
||||
from discord import SelectOption
|
||||
@ -4243,6 +4244,34 @@ async def get_game_summary_embed(
|
||||
return game_embed
|
||||
|
||||
|
||||
async def _trigger_variant_renders(tier_ups: list) -> None:
|
||||
"""Fire-and-forget: hit card render URLs to trigger S3 upload for new variants.
|
||||
|
||||
Each tier-up with a variant_created value gets a GET request to the card
|
||||
render endpoint, which triggers Playwright render + S3 upload as a side effect.
|
||||
Failures are logged but never raised.
|
||||
"""
|
||||
today = datetime.date.today().isoformat()
|
||||
for tier_up in tier_ups:
|
||||
variant = tier_up.get("variant_created")
|
||||
if not variant:
|
||||
continue
|
||||
player_id = tier_up["player_id"]
|
||||
track = tier_up.get("track_name", "Batter")
|
||||
card_type = "pitching" if track.lower() == "pitcher" else "batting"
|
||||
try:
|
||||
await db_get(
|
||||
f"players/{player_id}/{card_type}card/{today}/{variant}",
|
||||
none_okay=True,
|
||||
)
|
||||
except Exception:
|
||||
logger.warning(
|
||||
"Failed to trigger variant render for player %d variant %d (non-fatal)",
|
||||
player_id,
|
||||
variant,
|
||||
)
|
||||
|
||||
|
||||
async def complete_game(
|
||||
session: Session,
|
||||
interaction: discord.Interaction,
|
||||
@ -4353,6 +4382,7 @@ async def complete_game(
|
||||
if evo_result and evo_result.get("tier_ups"):
|
||||
for tier_up in evo_result["tier_ups"]:
|
||||
await notify_tier_completion(interaction.channel, tier_up)
|
||||
await _trigger_variant_renders(evo_result["tier_ups"])
|
||||
except Exception as e:
|
||||
logger.warning(f"Post-game refractor processing failed (non-fatal): {e}")
|
||||
|
||||
|
||||
65
tests/test_post_game_render.py
Normal file
65
tests/test_post_game_render.py
Normal file
@ -0,0 +1,65 @@
|
||||
"""Tests for post-game refractor card render trigger."""
|
||||
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
from command_logic.logic_gameplay import _trigger_variant_renders
|
||||
|
||||
|
||||
class TestTriggerVariantRenders:
|
||||
"""Fire-and-forget card render calls after tier-ups."""
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_calls_render_url_for_each_tier_up(self):
|
||||
"""Each tier-up with variant_created triggers a card render GET request."""
|
||||
tier_ups = [
|
||||
{"player_id": 100, "variant_created": 7, "track_name": "Batter"},
|
||||
{"player_id": 200, "variant_created": 3, "track_name": "Pitcher"},
|
||||
]
|
||||
|
||||
with patch(
|
||||
"command_logic.logic_gameplay.db_get", new_callable=AsyncMock
|
||||
) as mock_get:
|
||||
mock_get.return_value = None
|
||||
await _trigger_variant_renders(tier_ups)
|
||||
|
||||
assert mock_get.call_count == 2
|
||||
call_args_list = [call.args[0] for call in mock_get.call_args_list]
|
||||
assert any("100" in url and "7" in url for url in call_args_list)
|
||||
assert any("200" in url and "3" in url for url in call_args_list)
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_skips_tier_ups_without_variant(self):
|
||||
"""Tier-ups without variant_created are skipped."""
|
||||
tier_ups = [
|
||||
{"player_id": 100, "track_name": "Batter"},
|
||||
]
|
||||
|
||||
with patch(
|
||||
"command_logic.logic_gameplay.db_get", new_callable=AsyncMock
|
||||
) as mock_get:
|
||||
await _trigger_variant_renders(tier_ups)
|
||||
mock_get.assert_not_called()
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_api_failure_does_not_raise(self):
|
||||
"""Render trigger failures are swallowed — fire-and-forget."""
|
||||
tier_ups = [
|
||||
{"player_id": 100, "variant_created": 7, "track_name": "Batter"},
|
||||
]
|
||||
|
||||
with patch(
|
||||
"command_logic.logic_gameplay.db_get", new_callable=AsyncMock
|
||||
) as mock_get:
|
||||
mock_get.side_effect = Exception("API down")
|
||||
await _trigger_variant_renders(tier_ups)
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_empty_tier_ups_is_noop(self):
|
||||
"""Empty tier_ups list does nothing."""
|
||||
with patch(
|
||||
"command_logic.logic_gameplay.db_get", new_callable=AsyncMock
|
||||
) as mock_get:
|
||||
await _trigger_variant_renders([])
|
||||
mock_get.assert_not_called()
|
||||
Loading…
Reference in New Issue
Block a user