- 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>
55 lines
1.6 KiB
Go
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
|
|
}
|