Merge pull request 'Fix Discord pick announcements arriving out of order and add 429 retry' (#51) from fix/discord-pick-announcement-ordering into main
Reviewed-on: #51
This commit is contained in:
commit
874a2db853
3 changed files with 55 additions and 33 deletions
|
|
@ -827,23 +827,8 @@ export async function executeAutoPick(params: {
|
||||||
logger.error("[AutoPick] Error updating Brackt EVs after pick:", error);
|
logger.error("[AutoPick] Error updating Brackt EVs after pick:", error);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if next team has autodraft enabled and trigger immediately
|
// Announce before triggering the chain so Discord messages arrive in pick-number
|
||||||
// Only run the chain from the top-level call to prevent recursion
|
// order. If the chain ran first, chained picks would announce before this one.
|
||||||
if (!isDraftComplete && params.chainEnabled !== false) {
|
|
||||||
await checkAndTriggerNextAutodraft({
|
|
||||||
seasonId,
|
|
||||||
nextPickNumber,
|
|
||||||
totalTeams,
|
|
||||||
draftSlots,
|
|
||||||
db,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Fire-and-forget: sendOnTheClockEmail fetches the current pick number from
|
|
||||||
// the DB itself, so it always sees the post-chain state without blocking here.
|
|
||||||
sendOnTheClockEmail({ seasonId, totalTeams, draftSlots, db })
|
|
||||||
.catch((err) => logger.error("[AutoPick] On-the-clock email failed:", err));
|
|
||||||
}
|
|
||||||
|
|
||||||
const pickedSlot = draftSlots.find((s) => s.teamId === teamId);
|
const pickedSlot = draftSlots.find((s) => s.teamId === teamId);
|
||||||
if (!pickedSlot) {
|
if (!pickedSlot) {
|
||||||
logger.warn(`[AutoPick] Skipping Discord pick announcement: no draft slot found for team ${teamId}`);
|
logger.warn(`[AutoPick] Skipping Discord pick announcement: no draft slot found for team ${teamId}`);
|
||||||
|
|
@ -865,6 +850,23 @@ export async function executeAutoPick(params: {
|
||||||
}).catch((err) => logger.error("[AutoPick] Discord pick announcement failed:", err));
|
}).catch((err) => logger.error("[AutoPick] Discord pick announcement failed:", err));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if next team has autodraft enabled and trigger immediately
|
||||||
|
// Only run the chain from the top-level call to prevent recursion
|
||||||
|
if (!isDraftComplete && params.chainEnabled !== false) {
|
||||||
|
await checkAndTriggerNextAutodraft({
|
||||||
|
seasonId,
|
||||||
|
nextPickNumber,
|
||||||
|
totalTeams,
|
||||||
|
draftSlots,
|
||||||
|
db,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Fire-and-forget: sendOnTheClockEmail fetches the current pick number from
|
||||||
|
// the DB itself, so it always sees the post-chain state without blocking here.
|
||||||
|
sendOnTheClockEmail({ seasonId, totalTeams, draftSlots, db })
|
||||||
|
.catch((err) => logger.error("[AutoPick] On-the-clock email failed:", err));
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
pick: draftPick,
|
pick: draftPick,
|
||||||
|
|
|
||||||
|
|
@ -303,6 +303,24 @@ export async function action(args: ActionFunctionArgs) {
|
||||||
logger.error("Socket.IO error:", error);
|
logger.error("Socket.IO error:", error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Announce before triggering the chain so Discord messages arrive in pick-number
|
||||||
|
// order. If the chain ran first, chained picks would announce before this one.
|
||||||
|
notifyPickMadeOnDiscord({
|
||||||
|
seasonId,
|
||||||
|
leagueId: season.leagueId,
|
||||||
|
pickedTeamName: currentDraftSlot.team.name,
|
||||||
|
participantName: participant.name,
|
||||||
|
sportName: participant.sportsSeason.sport.name,
|
||||||
|
pickNumber: currentPickNumber,
|
||||||
|
nextPickNumber,
|
||||||
|
round: currentRound,
|
||||||
|
rawPickInRound,
|
||||||
|
isDraftComplete,
|
||||||
|
totalTeams,
|
||||||
|
draftSlots: draftSlots.map((s) => ({ teamId: s.teamId, draftOrder: s.draftOrder })),
|
||||||
|
db,
|
||||||
|
}).catch((err) => logger.error("Discord pick announcement failed:", err));
|
||||||
|
|
||||||
// Check if next team has autodraft enabled and trigger immediately
|
// Check if next team has autodraft enabled and trigger immediately
|
||||||
if (!isDraftComplete) {
|
if (!isDraftComplete) {
|
||||||
try {
|
try {
|
||||||
|
|
@ -331,22 +349,6 @@ export async function action(args: ActionFunctionArgs) {
|
||||||
.catch((err) => logger.error("On-the-clock email failed:", err));
|
.catch((err) => logger.error("On-the-clock email failed:", err));
|
||||||
}
|
}
|
||||||
|
|
||||||
notifyPickMadeOnDiscord({
|
|
||||||
seasonId,
|
|
||||||
leagueId: season.leagueId,
|
|
||||||
pickedTeamName: currentDraftSlot.team.name,
|
|
||||||
participantName: participant.name,
|
|
||||||
sportName: participant.sportsSeason.sport.name,
|
|
||||||
pickNumber: currentPickNumber,
|
|
||||||
nextPickNumber,
|
|
||||||
round: currentRound,
|
|
||||||
rawPickInRound,
|
|
||||||
isDraftComplete,
|
|
||||||
totalTeams,
|
|
||||||
draftSlots: draftSlots.map((s) => ({ teamId: s.teamId, draftOrder: s.draftOrder })),
|
|
||||||
db,
|
|
||||||
}).catch((err) => logger.error("Discord pick announcement failed:", err));
|
|
||||||
|
|
||||||
return Response.json({
|
return Response.json({
|
||||||
success: true,
|
success: true,
|
||||||
pick: draftPick,
|
pick: draftPick,
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,24 @@ export async function sendDiscordWebhook(
|
||||||
body: JSON.stringify(payload),
|
body: JSON.stringify(payload),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (response.status === 429) {
|
||||||
|
// Cap at 10 s so awaited callers (e.g. settings actions) are never hung for
|
||||||
|
// a full Discord global-rate-limit window. Use || 1 instead of ?? 1 so that
|
||||||
|
// NaN (non-numeric header) and 0 both fall back to a 1-second default.
|
||||||
|
const retryAfterSeconds = Math.min(Number(response.headers.get("Retry-After")) || 1, 10);
|
||||||
|
await new Promise((r) => setTimeout(r, retryAfterSeconds * 1000));
|
||||||
|
const retry = await fetch(webhookUrl, {
|
||||||
|
method: "POST",
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
body: JSON.stringify(payload),
|
||||||
|
});
|
||||||
|
if (!retry.ok) {
|
||||||
|
const text = await retry.text().catch(() => "");
|
||||||
|
throw new Error(`Discord webhook failed after retry: ${retry.status} ${text}`);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
const text = await response.text().catch(() => "");
|
const text = await response.text().catch(() => "");
|
||||||
throw new Error(`Discord webhook failed: ${response.status} ${text}`);
|
throw new Error(`Discord webhook failed: ${response.status} ${text}`);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue