feat: webhooker 1.0 MVP — entity rename, core engine, delivery, management UI #16
19
internal/database/model_archived_event.go
Normal file
19
internal/database/model_archived_event.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package database
|
||||
|
||||
// ArchivedEvent stores webhook events delivered via the "database" target type.
|
||||
// These records persist independently of internal event retention and pruning,
|
||||
// providing a durable archive for downstream consumption.
|
||||
type ArchivedEvent struct {
|
||||
BaseModel
|
||||
|
||||
WebhookID string `gorm:"type:uuid;not null;index" json:"webhook_id"`
|
||||
EntrypointID string `gorm:"type:uuid;not null" json:"entrypoint_id"`
|
||||
EventID string `gorm:"type:uuid;not null" json:"event_id"`
|
||||
TargetID string `gorm:"type:uuid;not null" json:"target_id"`
|
||||
|
||||
// Original request data (copied from Event at archive time)
|
||||
Method string `gorm:"not null" json:"method"`
|
||||
Headers string `gorm:"type:text" json:"headers"` // JSON
|
||||
Body string `gorm:"type:text" json:"body"`
|
||||
ContentType string `json:"content_type"`
|
||||
}
|
||||
@@ -11,5 +11,6 @@ func (d *Database) Migrate() error {
|
||||
&Event{},
|
||||
&Delivery{},
|
||||
&DeliveryResult{},
|
||||
&ArchivedEvent{},
|
||||
)
|
||||
}
|
||||
|
||||
@@ -244,7 +244,32 @@ func (e *Engine) deliverRetry(_ context.Context, d *database.Delivery) {
|
||||
}
|
||||
|
||||
func (e *Engine) deliverDatabase(d *database.Delivery) {
|
||||
// The event is already stored in the database; mark as delivered.
|
||||
// Write the event to the dedicated archived_events table. This table
|
||||
// persists independently of internal event retention/pruning, so the
|
||||
// data remains available for external consumption even after the
|
||||
// original event is cleaned up.
|
||||
archived := &database.ArchivedEvent{
|
||||
WebhookID: d.Event.WebhookID,
|
||||
EntrypointID: d.Event.EntrypointID,
|
||||
EventID: d.EventID,
|
||||
TargetID: d.TargetID,
|
||||
Method: d.Event.Method,
|
||||
Headers: d.Event.Headers,
|
||||
Body: d.Event.Body,
|
||||
ContentType: d.Event.ContentType,
|
||||
}
|
||||
|
||||
if err := e.database.DB().Create(archived).Error; err != nil {
|
||||
e.log.Error("failed to archive event",
|
||||
"delivery_id", d.ID,
|
||||
"event_id", d.EventID,
|
||||
"error", err,
|
||||
)
|
||||
e.recordResult(d, 1, false, 0, "", err.Error(), 0)
|
||||
e.updateDeliveryStatus(d, database.DeliveryStatusFailed)
|
||||
return
|
||||
}
|
||||
|
||||
e.recordResult(d, 1, true, 0, "", "", 0)
|
||||
e.updateDeliveryStatus(d, database.DeliveryStatusDelivered)
|
||||
}
|
||||
|
||||
@@ -100,17 +100,17 @@ func (s *Server) SetupRoutes() {
|
||||
|
||||
s.router.Route("/source/{sourceID}", func(r chi.Router) {
|
||||
r.Use(s.mw.RequireAuth())
|
||||
r.Get("/", s.h.HandleSourceDetail()) // View webhook details
|
||||
r.Get("/edit", s.h.HandleSourceEdit()) // Show edit form
|
||||
r.Post("/edit", s.h.HandleSourceEditSubmit()) // Handle edit submission
|
||||
r.Post("/delete", s.h.HandleSourceDelete()) // Delete webhook
|
||||
r.Get("/logs", s.h.HandleSourceLogs()) // View webhook logs
|
||||
r.Post("/entrypoints", s.h.HandleEntrypointCreate()) // Add entrypoint
|
||||
r.Post("/entrypoints/{entrypointID}/delete", s.h.HandleEntrypointDelete()) // Delete entrypoint
|
||||
r.Post("/entrypoints/{entrypointID}/toggle", s.h.HandleEntrypointToggle()) // Toggle entrypoint active
|
||||
r.Post("/targets", s.h.HandleTargetCreate()) // Add target
|
||||
r.Post("/targets/{targetID}/delete", s.h.HandleTargetDelete()) // Delete target
|
||||
r.Post("/targets/{targetID}/toggle", s.h.HandleTargetToggle()) // Toggle target active
|
||||
r.Get("/", s.h.HandleSourceDetail()) // View webhook details
|
||||
r.Get("/edit", s.h.HandleSourceEdit()) // Show edit form
|
||||
r.Post("/edit", s.h.HandleSourceEditSubmit()) // Handle edit submission
|
||||
r.Post("/delete", s.h.HandleSourceDelete()) // Delete webhook
|
||||
r.Get("/logs", s.h.HandleSourceLogs()) // View webhook logs
|
||||
r.Post("/entrypoints", s.h.HandleEntrypointCreate()) // Add entrypoint
|
||||
r.Post("/entrypoints/{entrypointID}/delete", s.h.HandleEntrypointDelete()) // Delete entrypoint
|
||||
r.Post("/entrypoints/{entrypointID}/toggle", s.h.HandleEntrypointToggle()) // Toggle entrypoint active
|
||||
r.Post("/targets", s.h.HandleTargetCreate()) // Add target
|
||||
r.Post("/targets/{targetID}/delete", s.h.HandleTargetDelete()) // Delete target
|
||||
r.Post("/targets/{targetID}/toggle", s.h.HandleTargetToggle()) // Toggle target active
|
||||
})
|
||||
|
||||
// Entrypoint endpoint — accepts incoming webhook POST requests only.
|
||||
|
||||
Reference in New Issue
Block a user