Files
honeyDueAPI/internal/repositories/webhook_event_repo.go
treyt e26116e2cf Add webhook logging, pagination, middleware, migrations, and prod hardening
- Webhook event logging repo and subscription webhook idempotency
- Pagination helper (echohelpers) with cursor/offset support
- Request ID and structured logging middleware
- Push client improvements (FCM HTTP v1, better error handling)
- Task model version column, business constraint migrations, targeted indexes
- Expanded categorization chain tests
- Email service and config hardening
- CI workflow updates, .gitignore additions, .env.example updates

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 21:32:09 -06:00

55 lines
1.6 KiB
Go

package repositories
import (
"time"
"gorm.io/gorm"
)
// WebhookEvent represents a processed webhook event for deduplication
type WebhookEvent struct {
ID uint `gorm:"primaryKey"`
EventID string `gorm:"column:event_id;size:255;not null;uniqueIndex:idx_provider_event_id"`
Provider string `gorm:"column:provider;size:20;not null;uniqueIndex:idx_provider_event_id"`
EventType string `gorm:"column:event_type;size:100;not null"`
ProcessedAt time.Time `gorm:"column:processed_at;autoCreateTime"`
PayloadHash string `gorm:"column:payload_hash;size:64"`
}
func (WebhookEvent) TableName() string {
return "webhook_event_log"
}
// WebhookEventRepository handles webhook event deduplication
type WebhookEventRepository struct {
db *gorm.DB
}
// NewWebhookEventRepository creates a new webhook event repository
func NewWebhookEventRepository(db *gorm.DB) *WebhookEventRepository {
return &WebhookEventRepository{db: db}
}
// HasProcessed checks if an event has already been processed
func (r *WebhookEventRepository) HasProcessed(provider, eventID string) (bool, error) {
var count int64
err := r.db.Model(&WebhookEvent{}).
Where("provider = ? AND event_id = ?", provider, eventID).
Count(&count).Error
if err != nil {
return false, err
}
return count > 0, nil
}
// RecordEvent records a processed webhook event
func (r *WebhookEventRepository) RecordEvent(provider, eventID, eventType, payloadHash string) error {
event := &WebhookEvent{
EventID: eventID,
Provider: provider,
EventType: eventType,
PayloadHash: payloadHash,
}
return r.db.Create(event).Error
}