Dual-dialect store (SQLite via modernc.org, MySQL via go-sql-driver, both pure Go) with order-tolerant start/complete upserts, filtered and paginated listing, and aggregate queries (per-day, top domains, query types, statuses, duration percentiles, top clients). Sender gains optional EXPLOREDNS_WEBHOOK_TOKEN bearer auth; a round-trip test pins receiver structs byte-compatible with the sender payloads. Note: go directive moves to 1.25.0, required by modernc.org/sqlite. CI reads the version from go.mod so GOTOOLCHAIN=local stays satisfied. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
40 lines
1.4 KiB
Go
40 lines
1.4 KiB
Go
package store
|
|
|
|
import (
|
|
"encoding/json"
|
|
"time"
|
|
)
|
|
|
|
// StartEvent and CompleteEvent are the receiver-side decodings of the
|
|
// webhook payloads posted by the main app. Field names and JSON tags must
|
|
// stay in sync with webhookStartEvent/webhookCompleteEvent in
|
|
// web/api/webhook.go; a compatibility test in web/api enforces this.
|
|
|
|
// StartEvent mirrors web/api webhookStartEvent.
|
|
type StartEvent struct {
|
|
Event string `json:"event"`
|
|
ID string `json:"id"`
|
|
Domain string `json:"domain"`
|
|
QueryType string `json:"query_type"`
|
|
AllRoots bool `json:"all_roots"`
|
|
ClientIP string `json:"client_ip"`
|
|
StartedAt time.Time `json:"started_at"`
|
|
}
|
|
|
|
// CompleteEvent mirrors web/api webhookCompleteEvent. Summary is kept as
|
|
// raw JSON: the receiver stores it verbatim and never interprets it.
|
|
type CompleteEvent struct {
|
|
Event string `json:"event"`
|
|
ID string `json:"id"`
|
|
Domain string `json:"domain"`
|
|
QueryType string `json:"query_type"`
|
|
ClientIP string `json:"client_ip"`
|
|
StartedAt time.Time `json:"started_at"`
|
|
DoneAt time.Time `json:"done_at"`
|
|
DurationMS int64 `json:"duration_ms"`
|
|
Status string `json:"status"`
|
|
Error string `json:"error,omitempty"`
|
|
ResultCount int `json:"result_count"`
|
|
Summary json.RawMessage `json:"summary"`
|
|
}
|