Event log: only the newest event expanded, and only the 50 most recent (closes #349)
check / check (push) Successful in 3m35s
check / check (push) Successful in 3m35s
The event log now loads the 50 newest events in its query and opens only the newest on load, as the recent events on a webhook's page already do. With 50 at most there is never a second page, so paging is gone: the page links, the `page` query parameter, the page number that Replay and Resubmit carried back to the log, and `pageOrFirst` with its test. The count beside the heading reads "50 most recent of N events" when there are more. The comments and README lines that named `page` as the query parameter the service reads now name `next` and `notice`. Model: opus-5-5
This commit is contained in:
@@ -1112,30 +1112,17 @@ func (h *Handlers) HandleSourceLogs() http.HandlerFunc {
|
||||
return
|
||||
}
|
||||
|
||||
page := h.parsePage(r)
|
||||
|
||||
evts, total, ok := h.loadEventsWithDeliveries(
|
||||
w, r, webhook, targets, page,
|
||||
w, r, webhook, targets,
|
||||
)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
totalPages := int(total) / paginationPerPage
|
||||
if int(total)%paginationPerPage != 0 {
|
||||
totalPages++
|
||||
}
|
||||
|
||||
data := map[string]any{
|
||||
tmplKeyWebhook: &webhook,
|
||||
"Events": evts,
|
||||
"Page": page,
|
||||
"TotalPages": totalPages,
|
||||
"TotalEvents": total,
|
||||
"HasPrev": page > 1,
|
||||
"HasNext": page < totalPages,
|
||||
"PrevPage": page - 1,
|
||||
"NextPage": page + 1,
|
||||
}
|
||||
|
||||
h.renderTemplate(w, r, "source_logs.html", data)
|
||||
@@ -1195,15 +1182,11 @@ func (h *Handlers) loadTargetMap(
|
||||
return targetMap, nil
|
||||
}
|
||||
|
||||
// parsePage extracts a page number from the query string.
|
||||
func (h *Handlers) parsePage(r *http.Request) int {
|
||||
return pageOrFirst(r.URL.Query().Get("page"))
|
||||
}
|
||||
|
||||
// loadEventsWithDeliveries loads paginated events and their
|
||||
// deliveries from the per-webhook database. Events come back
|
||||
// as capped projections rather than database.Event rows: see
|
||||
// eventLogColumns for why the cut happens in SQL.
|
||||
// loadEventsWithDeliveries loads the recentEventLimit newest events
|
||||
// and their deliveries from the per-webhook database, and the total
|
||||
// number of events stored. Events come back as capped projections
|
||||
// rather than database.Event rows: see eventLogColumns for why the
|
||||
// cut happens in SQL.
|
||||
//
|
||||
// The bool reports whether the load succeeded. It is false
|
||||
// once this has answered the request with an error, and the
|
||||
@@ -1213,7 +1196,6 @@ func (h *Handlers) loadEventsWithDeliveries(
|
||||
r *http.Request,
|
||||
webhook database.Webhook,
|
||||
targetMap map[string]eventLogTarget,
|
||||
page int,
|
||||
) ([]EventLogView, int64, bool) {
|
||||
if !h.dbMgr.DBExists(webhook.ID) {
|
||||
return nil, 0, true
|
||||
@@ -1228,9 +1210,7 @@ func (h *Handlers) loadEventsWithDeliveries(
|
||||
return nil, 0, false
|
||||
}
|
||||
|
||||
rows, totalEvents := loadEventLogRows(
|
||||
webhookDB, webhook.ID, page,
|
||||
)
|
||||
rows, totalEvents := loadEventLogRows(webhookDB, webhook.ID)
|
||||
|
||||
result, ok := h.eventLogViews(
|
||||
w, r, webhookDB, webhook.ID, rows, targetMap,
|
||||
@@ -1303,10 +1283,11 @@ func (h *Handlers) eventLogViews(
|
||||
return result, true
|
||||
}
|
||||
|
||||
// loadEventLogRows reads one page of the event log projection, newest
|
||||
// first, and the total number of events the pager counts against.
|
||||
// loadEventLogRows reads the event log projection of the
|
||||
// recentEventLimit newest events, newest first, and the total number
|
||||
// of events stored.
|
||||
func loadEventLogRows(
|
||||
webhookDB *gorm.DB, webhookID string, page int,
|
||||
webhookDB *gorm.DB, webhookID string,
|
||||
) ([]eventLogRow, int64) {
|
||||
var totalEvents int64
|
||||
|
||||
@@ -1320,9 +1301,7 @@ func loadEventLogRows(
|
||||
eventLogColumns, maxRenderedBodyBytes,
|
||||
).Where(
|
||||
"webhook_id = ?", webhookID,
|
||||
).Order("created_at DESC").Offset(
|
||||
(page - 1) * paginationPerPage,
|
||||
).Limit(paginationPerPage).Find(&rows)
|
||||
).Order("created_at DESC").Limit(recentEventLimit).Find(&rows)
|
||||
|
||||
return rows, totalEvents
|
||||
}
|
||||
@@ -1331,9 +1310,9 @@ func loadEventLogRows(
|
||||
// events have been resubmitted from it.
|
||||
//
|
||||
// One grouped query covers the page rather than one query per event.
|
||||
// A page holds paginationPerPage ids, far below SQLite's bound
|
||||
// parameter ceiling, so it needs no chunking as the delivery result
|
||||
// load does.
|
||||
// The page shows at most recentEventLimit events, far below SQLite's
|
||||
// bound parameter ceiling, so it needs no chunking as the delivery
|
||||
// result load does.
|
||||
func resubmitCounts(
|
||||
webhookDB *gorm.DB, eventIDs []string,
|
||||
) (map[string]int, error) {
|
||||
@@ -1759,24 +1738,6 @@ func (h *Handlers) setTargetFromForm(
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// pageOrFirst parses a paginated page number, answering 1 for
|
||||
// anything empty, unparseable or out of range.
|
||||
//
|
||||
// Falling back rather than rejecting is correct here and only here:
|
||||
// a page number is where to send the browser next, not configuration
|
||||
// the operator is storing, and the actions that submit one have
|
||||
// already completed by the time it is read — answering 400 would
|
||||
// report a failure that did not happen. Anything an operator SETS
|
||||
// must be validated instead; see parseMaxRetries.
|
||||
func pageOrFirst(s string) int {
|
||||
v, err := strconv.Atoi(strings.TrimSpace(s))
|
||||
if err != nil || v < 1 {
|
||||
return 1
|
||||
}
|
||||
|
||||
return v
|
||||
}
|
||||
|
||||
// targetFormInput carries the raw values of a target form. Both the
|
||||
// create and the edit path fill one and hand it to setTargetFromForm,
|
||||
// so neither can come to validate a target differently from the
|
||||
|
||||
Reference in New Issue
Block a user