Compare commits

1 Commits
Author SHA1 Message Date
sneak 843bcd2eb4 Index the event log's resubmit count with deleted_at (closes #325)
check / check (push) Successful in 3m21s
The resubmit count matches resubmitted_from_id against a page of event
ids, and GORM adds deleted_at IS NULL. With no statistics, SQLite
preferred the deleted_at index once the page held five or more ids, so
every event log page read every live event. deleted_at now joins
resubmitted_from_id in idx_events_resubmitted_from_id, as for the other
event-tier indexes, and the plan test checks the statement with a full
page of ids.

Model: opus-5-5
2026-10-02 18:43:38 +00:00
4 changed files with 9 additions and 22 deletions
-1
View File
@@ -25,7 +25,6 @@ COPY . .
# would need a docker daemon inside the build. Keep these steps in step with # would need a docker daemon inside the build. Keep these steps in step with
# Dockerfile.lint, including --network=none (see its header for why). # Dockerfile.lint, including --network=none (see its header for why).
RUN make fmt-check RUN make fmt-check
RUN script/assets
RUN --network=none golangci-lint config verify --config .golangci.yml RUN --network=none golangci-lint config verify --config .golangci.yml
RUN --network=none golangci-lint run --config .golangci.yml --build-tags browser ./... RUN --network=none golangci-lint run --config .golangci.yml --build-tags browser ./...
-4
View File
@@ -31,10 +31,6 @@ FROM deps AS lint
COPY . . COPY . .
# static/static.go embeds the Alpine.js file this extracts from 3p/; without
# it the static package does not compile and cannot be linted.
RUN script/assets
# `run` silently ignores config keys it does not recognize, so a typo would # `run` silently ignores config keys it does not recognize, so a typo would
# disable a setting without a word. `config verify` is what catches that. # disable a setting without a word. `config verify` is what catches that.
RUN --network=none golangci-lint config verify --config .golangci.yml RUN --network=none golangci-lint config verify --config .golangci.yml
+7 -12
View File
@@ -1348,9 +1348,7 @@ apply. The directory is `3p/` rather than `vendor/` because Go treats a root
where `go:embed` picks it up. `script/test`, `make build` and `make dev` run where `go:embed` picks it up. `script/test`, `make build` and `make dev` run
it first, and the Dockerfile builds through `make test` and `make build`, so it first, and the Dockerfile builds through `make test` and `make build`, so
nothing downloads Alpine.js. The extracted file is not committed, and nothing downloads Alpine.js. The extracted file is not committed, and
`.dockerignore` keeps any host copy out of the build context. `static/static.go` `.dockerignore` keeps any host copy out of the build context.
names every file it embeds, so a build that skips the extraction, such as a
bare `go build`, fails with an error naming `js/alpine.min.js`.
To move to a new version: download To move to a new version: download
`https://registry.npmjs.org/@alpinejs/csp/-/csp-<version>.tgz`, check it against `https://registry.npmjs.org/@alpinejs/csp/-/csp-<version>.tgz`, check it against
@@ -1885,12 +1883,10 @@ GORM's soft delete adds `deleted_at IS NULL` to these queries; retention
leaves it out. SQLite keeps no statistics on these tables, and without them it leaves it out. SQLite keeps no statistics on these tables, and without them it
rates the `deleted_at` index, which every live row matches, above an index on rates the `deleted_at` index, which every live row matches, above an index on
a column matched against several values or compared with a range. So every a column matched against several values or compared with a range. So every
index but the last also covers `deleted_at`. It comes second in the `event_id` index but the last also covers `deleted_at`. It comes second, so that
and `delivery_id` indexes, so that retention can use them without it. The event retention can use the index without it, except in the statistics' `events`
log's count, the one query on the `resubmitted_from_id` index, always carries index, where they compare `created_at` with a range (`>=`) and SQLite narrows
`deleted_at IS NULL` and uses both columns. In the statistics' `events` index by a range only on the last column it uses.
`deleted_at` comes first, because they compare `created_at` with a range (`>=`)
and SQLite narrows by a range only on the last column it uses.
#### Common Fields #### Common Fields
@@ -3384,9 +3380,8 @@ version is fixed independently of the compiler's:
1. **Lint stage** (`golangci/golangci-lint:v2.12.2`, Debian-based) — 1. **Lint stage** (`golangci/golangci-lint:v2.12.2`, Debian-based) —
installs `make`, downloads dependencies, copies the source, and runs installs `make`, downloads dependencies, copies the source, and runs
`make fmt-check`, then `script/assets` to extract Alpine.js from `make fmt-check`, then `golangci-lint config verify` and
`3p/`, then `golangci-lint config verify` and `golangci-lint run`, `golangci-lint run`, both with `--network=none`.
both with `--network=none`.
2. **Builder stage** (`golang:1.26.1-bookworm`) — depends on the lint 2. **Builder stage** (`golang:1.26.1-bookworm`) — depends on the lint
stage passing (it copies a file from it), runs `make test` and stage passing (it copies a file from it), runs `make test` and
`make build` (both extract Alpine.js from `3p/` first), and finally `make build` (both extract Alpine.js from `3p/` first), and finally
+2 -5
View File
@@ -5,10 +5,7 @@ import (
"embed" "embed"
) )
// Static holds the CSS and JavaScript files the web UI's pages load. They // Static holds the embedded CSS and JavaScript files for the web UI.
// are named one by one so that a missing js/alpine.min.js, which make
// assets extracts and git does not track, fails the build instead of
// leaving the pages without Alpine.js.
// //
//go:embed css/tailwind.css css/style.css js/app.js js/alpine.min.js //go:embed css js
var Static embed.FS var Static embed.FS