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 }