feat: toast dedupe alignment, per-type cooldown, and reconnect suppression

- Align local mutation dedupe keys with live event keys so the same
  action doesn't produce two toasts (local success + live event)
- Add per-type cooldown gate (max 3 toasts per category in 10s) to
  suppress rapid-fire events from chatty sources
- Suppress all live-event toasts for 2s after WebSocket reconnect to
  avoid burst floods from cached server events
- TTL tuning by severity already applied externally (info=4s,
  success=3.5s, warn=8s, error=10s)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Forgotten
2026-02-20 13:56:34 -06:00
parent 5b06118ec8
commit 1b6db764b8
3 changed files with 53 additions and 8 deletions

View File

@@ -258,7 +258,7 @@ export function IssueDetail() {
onSuccess: (updated) => {
invalidateIssue();
pushToast({
dedupeKey: `issue-updated-${updated.id}`,
dedupeKey: `activity:issue.updated:${updated.id}`,
title: "Issue updated",
tone: "success",
});
@@ -272,7 +272,7 @@ export function IssueDetail() {
invalidateIssue();
queryClient.invalidateQueries({ queryKey: queryKeys.issues.comments(issueId!) });
pushToast({
dedupeKey: `issue-comment-${issueId}`,
dedupeKey: `activity:issue.comment_added:${issueId}`,
title: "Comment posted",
tone: "success",
});