fix(dataset): guard typed-nil previous value when closing replaced view

`any(typedNilPtr)` wraps the nil pointer in a non-nil interface, so the
prior `closer != nil` check didn't catch it — calling Close on the
underlying nil *geoip.Databases segfaulted during the first successful
reload after a failed one.

Also flip form2mail's default blocklist URL from git@ (SSH) to
https:// so fresh deployments work without a GitHub SSH key.
This commit is contained in:
AJ ONeal 2026-04-20 22:20:08 -06:00
parent 950aea9eeb
commit 9e46d5ce90
No known key found for this signature in database
2 changed files with 9 additions and 4 deletions

View File

@ -33,7 +33,7 @@ const (
licenseOwner = "AJ ONeal"
licenseType = "CC0-1.0"
defaultBlocklistRepo = "git@github.com:bitwire-it/ipblocklist.git"
defaultBlocklistRepo = "https://github.com/bitwire-it/ipblocklist.git"
refreshInterval = 47 * time.Minute
requestsPerMinute = 5

View File

@ -186,9 +186,14 @@ func (v *View[T]) reload(ctx context.Context) error {
// Close the replaced value if it holds OS resources (open file handles,
// network connections). Geoip readers and similar wrappers implement
// io.Closer; cohort and other pure-in-memory values don't — the type
// assertion filters to only the ones that need it.
if closer, ok := any(prev).(io.Closer); ok && closer != nil {
_ = closer.Close()
// assertion filters to only the ones that need it. The `prev != nil`
// guard is required because any(typedNilPtr) is a non-nil interface
// wrapping a nil pointer — the type assertion succeeds and we'd
// call Close on a nil receiver.
if prev != nil {
if closer, ok := any(prev).(io.Closer); ok {
_ = closer.Close()
}
}
now := time.Now()
v.loadedAt.Store(&now)