One-shot migration over the stored config and TLS rows, guarded by a setting
so it runs once:
- dns.independent_cache is dropped (1.14 reads it only to warn; the value is
never passed to the DNS client)
- experimental.cache_file.store_rdrc becomes store_dns
- route.rule_set[].download_detour becomes the http_client 1.14 builds for it
- inline tls.acme becomes tls.certificate_provider with type "acme"
Legacy DNS address filters and the `strategy` DNS rule action are NOT migrated
automatically. Converting them means inserting evaluate rules and reordering,
which changes how names resolve, so they are logged with the upstream
migration link for the operator to handle.
Tests cover each rewrite, that unrelated options survive, that a config with
nothing to migrate is left byte-identical, and that the migrated shapes build
a box with no deprecation warning.
SaveStats returned tx.Create().Error directly without assigning to the
local err variable, so the deferred closure always saw err==nil and
called Commit() on a failed transaction. This left the underlying
go-sqlite3 connection unreturned to the pool. With StatsJob firing
every 10s, leaked connections accumulated ~150 KB each, reaching
400+ MB after ~33 hours.
Fixes:
- stats.go: assign Create result to err so defer can Rollback on failure
- backup.go: defer-close backupDb to prevent pool leak on early return
- migration/main.go: defer-close migration db
- db.go: add ConnMaxIdleTime(5m), lower MaxIdleConns to 2, set
_cache_size=-200 to reduce per-connection memory from ~2 MB to ~200 KB
Measured: RSS dropped from 419 MB to 66 MB, db file descriptors from
4484 to 6, with zero growth over 3-minute observation window.