audit: fix issues #1-#9 (mock data, notifier interface, retry/timeout, digest scheduling, real status, RPC retry, dedup, address edit UI)
- #1: remove mock alert events that poisoned production responses - #2: add Notifier interface + Send implementations for all channels - #3/#4: notification goroutines now carry a 30s context timeout and retry up to 3x with exponential backoff - #5: schedule email digest in poller via DIGEST_INTERVAL_HOURS (default 24h) - #6: SystemStatus queries real checkpoint data; returns starting/active/idle with latestBlock and lag - #7: Ethereum RPC client retries on network errors, 429, and 5xx with 1s/2s backoff - #8: alert_events dedup index + ON CONFLICT DO NOTHING to prevent duplicate events on poller restart - #9: PATCH /v1/addresses/{id} for label editing; frontend address list gains inline edit and remove buttons
This commit is contained in:
@@ -2,6 +2,7 @@ package notifications
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
@@ -25,11 +26,15 @@ var discordHTTPClient = &http.Client{ //nolint:gochecknoglobals
|
||||
Timeout: discordHTTPTimeoutSeconds * time.Second,
|
||||
}
|
||||
|
||||
type AlertMetadata struct {
|
||||
TxHash string
|
||||
AddressLabel string
|
||||
AlertType string
|
||||
Address string
|
||||
// DiscordNotifier sends alert notifications via a Discord webhook.
|
||||
type DiscordNotifier struct {
|
||||
WebhookURL string
|
||||
}
|
||||
|
||||
// Send implements Notifier for Discord.
|
||||
func (d *DiscordNotifier) Send(_ context.Context, message string, meta AlertMetadata) error {
|
||||
_, err := SendDiscordNotification(d.WebhookURL, message, meta)
|
||||
return err
|
||||
}
|
||||
|
||||
type discordEmbed struct {
|
||||
|
||||
@@ -2,6 +2,7 @@ package notifications
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
@@ -9,6 +10,19 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// EmailNotifier sends alert notifications via email (Resend).
|
||||
type EmailNotifier struct {
|
||||
APIKey string
|
||||
From string
|
||||
To string
|
||||
}
|
||||
|
||||
// Send implements Notifier for email.
|
||||
func (e *EmailNotifier) Send(_ context.Context, message string, meta AlertMetadata) error {
|
||||
_, err := SendEmailNotification(e.APIKey, e.From, e.To, message, meta)
|
||||
return err
|
||||
}
|
||||
|
||||
const emailHTTPTimeoutSeconds = 10
|
||||
|
||||
var emailHTTPClient = &http.Client{ //nolint:gochecknoglobals
|
||||
|
||||
16
backend-go/internal/notifications/notifier.go
Normal file
16
backend-go/internal/notifications/notifier.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package notifications
|
||||
|
||||
import "context"
|
||||
|
||||
// AlertMetadata holds context about the alert being sent.
|
||||
type AlertMetadata struct {
|
||||
TxHash string
|
||||
AddressLabel string
|
||||
AlertType string
|
||||
Address string
|
||||
}
|
||||
|
||||
// Notifier is the interface implemented by all notification channels.
|
||||
type Notifier interface {
|
||||
Send(ctx context.Context, message string, meta AlertMetadata) error
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package notifications
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
@@ -9,6 +10,17 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// SlackNotifier sends alert notifications via a Slack webhook.
|
||||
type SlackNotifier struct {
|
||||
WebhookURL string
|
||||
}
|
||||
|
||||
// Send implements Notifier for Slack.
|
||||
func (s *SlackNotifier) Send(_ context.Context, message string, meta AlertMetadata) error {
|
||||
_, err := SendSlackNotification(s.WebhookURL, message, meta)
|
||||
return err
|
||||
}
|
||||
|
||||
const slackHTTPTimeoutSeconds = 10
|
||||
|
||||
var slackHTTPClient = &http.Client{ //nolint:gochecknoglobals
|
||||
|
||||
@@ -2,6 +2,7 @@ package notifications
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
@@ -9,6 +10,18 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// TelegramNotifier sends alert notifications via Telegram.
|
||||
type TelegramNotifier struct {
|
||||
BotToken string
|
||||
ChatID string
|
||||
}
|
||||
|
||||
// Send implements Notifier for Telegram.
|
||||
func (t *TelegramNotifier) Send(_ context.Context, message string, meta AlertMetadata) error {
|
||||
_, err := SendTelegramNotification(t.BotToken, t.ChatID, message, meta)
|
||||
return err
|
||||
}
|
||||
|
||||
const telegramHTTPTimeoutSeconds = 10
|
||||
|
||||
var telegramHTTPClient = &http.Client{ //nolint:gochecknoglobals
|
||||
|
||||
Reference in New Issue
Block a user