check / check (push) Successful in 3m56s
The webhook page opens with a statistics pane: entrypoints and targets, deliveries in progress, the last arrival, the retention period; events, deliveries and failures, lifetime and within retention; and events, failures and failure percentage over 10 minutes and 24 hours. Running totals, one row per target plus one for events, sit in each webhook's event database and are written in the same transaction as the rows they count; retention prunes in paused, stoppable batches and subtracts what it removes. Window figures are index-range counts on a new finished_at column. An existing event database must be recreated. Model: opus-5-5
64 lines
2.2 KiB
Go
64 lines
2.2 KiB
Go
package database
|
|
|
|
import (
|
|
"time"
|
|
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// DeliveryStatus represents the status of a delivery
|
|
type DeliveryStatus string
|
|
|
|
// Delivery status values.
|
|
const (
|
|
DeliveryStatusPending DeliveryStatus = "pending"
|
|
DeliveryStatusDelivered DeliveryStatus = "delivered"
|
|
DeliveryStatusFailed DeliveryStatus = "failed"
|
|
DeliveryStatusRetrying DeliveryStatus = "retrying"
|
|
)
|
|
|
|
// Terminal reports whether a delivery in this status has finished, so
|
|
// the delivery engine will make no further attempt of its own.
|
|
//
|
|
// It is what decides which deliveries the event log offers to replay:
|
|
// a pending or retrying delivery is still the engine's, and replaying
|
|
// one would race it.
|
|
func (s DeliveryStatus) Terminal() bool {
|
|
switch s {
|
|
case DeliveryStatusDelivered, DeliveryStatusFailed:
|
|
return true
|
|
case DeliveryStatusPending, DeliveryStatusRetrying:
|
|
return false
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
// Delivery represents a delivery attempt for an event to a target
|
|
//
|
|
//nolint:lll // a struct tag cannot wrap
|
|
type Delivery struct {
|
|
BaseModel
|
|
|
|
EventID string `gorm:"type:uuid;not null;index:idx_deliveries_event_id,priority:1" json:"eventId"`
|
|
TargetID string `gorm:"type:uuid;not null;index:idx_deliveries_status,priority:4" json:"targetId"`
|
|
Status DeliveryStatus `gorm:"not null;default:'pending';index:idx_deliveries_status,priority:1" json:"status"`
|
|
|
|
// DeletedAt repeats the BaseModel field only to be the second column
|
|
// of the event_id and status indexes, for the reason DeliveryResult
|
|
// gives.
|
|
DeletedAt gorm.DeletedAt `gorm:"index:idx_deliveries_event_id,priority:2;index:idx_deliveries_status,priority:2" json:"deletedAt,omitzero"`
|
|
|
|
// FinishedAt is when the delivery became delivered or failed, and
|
|
// nil while it is pending or retrying. It and then TargetID end the
|
|
// status index, so the webhook page counts each target's deliveries
|
|
// that finished in a recent window by reading just that window from
|
|
// the index.
|
|
FinishedAt *time.Time `gorm:"index:idx_deliveries_status,priority:3" json:"finishedAt,omitempty"`
|
|
|
|
// Relations
|
|
Event Event `json:"event,omitzero"`
|
|
Target Target `json:"target,omitzero"`
|
|
DeliveryResults []DeliveryResult `json:"deliveryResults,omitempty"`
|
|
}
|