[bugfix] Return useful err on server start failure

This commit is contained in:
tobi 2025-03-05 15:45:35 +01:00
commit 85d4994b96
5 changed files with 73 additions and 50 deletions

View file

@ -22,6 +22,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"net/http" "net/http"
"net/netip"
"os" "os"
"os/signal" "os/signal"
"runtime" "runtime"
@ -117,9 +118,11 @@ var Start action.GTSAction = func(ctx context.Context) error {
) )
defer func() { defer func() {
// Stop caches with if state.Caches.Inited() {
// background tasks. // We reached a point where caches
// were initialized. Stop them.
state.Caches.Stop() state.Caches.Stop()
}
if route != nil { if route != nil {
// We reached a point where the API router // We reached a point where the API router
@ -133,6 +136,8 @@ var Start action.GTSAction = func(ctx context.Context) error {
// Stop any currently running // Stop any currently running
// worker processes / scheduled // worker processes / scheduled
// tasks from being executed. // tasks from being executed.
//
// Noop on unstarted workers.
state.Workers.Stop() state.Workers.Stop()
if state.Timelines.Home != nil { if state.Timelines.Home != nil {
@ -240,10 +245,17 @@ var Start action.GTSAction = func(ctx context.Context) error {
return fmt.Errorf("error opening storage backend: %w", err) return fmt.Errorf("error opening storage backend: %w", err)
} }
// Parse http client allow
// and block range exceptions.
ranges, err := parseClientRanges()
if err != nil {
return err
}
// Prepare wrapped httpclient with config. // Prepare wrapped httpclient with config.
client := httpclient.New(httpclient.Config{ client := httpclient.New(httpclient.Config{
AllowRanges: config.MustParseIPPrefixes(config.GetHTTPClientAllowIPs()), AllowRanges: ranges.allow,
BlockRanges: config.MustParseIPPrefixes(config.GetHTTPClientBlockIPs()), BlockRanges: ranges.block,
Timeout: config.GetHTTPClientTimeout(), Timeout: config.GetHTTPClientTimeout(),
TLSInsecureSkipVerify: config.GetHTTPClientTLSInsecureSkipVerify(), TLSInsecureSkipVerify: config.GetHTTPClientTLSInsecureSkipVerify(),
}) })
@ -617,3 +629,44 @@ func compileWASM(ctx context.Context) error {
return nil return nil
} }
func parseClientRanges() (
*struct {
allow []netip.Prefix
block []netip.Prefix
},
error,
) {
parseF := func(ips []string, ranges []netip.Prefix, flag string) error {
for i, ip := range ips {
p, err := netip.ParsePrefix(ip)
if err != nil {
return fmt.Errorf("error parsing %s value %s: %w", flag, ip, err)
}
ranges[i] = p
}
return nil
}
allowIPs := config.GetHTTPClientAllowIPs()
allowRanges := make([]netip.Prefix, len(allowIPs))
allowFlag := config.HTTPClientAllowIPsFlag()
if err := parseF(allowIPs, allowRanges, allowFlag); err != nil {
return nil, err
}
blockIPs := config.GetHTTPClientBlockIPs()
blockRanges := make([]netip.Prefix, len(blockIPs))
blockFlag := config.HTTPClientBlockIPsFlag()
if err := parseF(blockIPs, blockRanges, blockFlag); err != nil {
return nil, err
}
return &struct {
allow []netip.Prefix
block []netip.Prefix
}{
allow: allowRanges,
block: blockRanges,
}, nil
}

View file

@ -136,6 +136,13 @@ func (c *Caches) Start() {
}) })
} }
// Inited returns true if the
// caches have been initialized.
func (c *Caches) Inited() bool {
// Use nilness of *ttl.Cache pointers as heuristic.
return c.Webfinger != nil && c.StatusesFilterableFields != nil
}
// Stop will stop any caches that require a background // Stop will stop any caches that require a background
// routine, which usually means any kind of TTL caches. // routine, which usually means any kind of TTL caches.
func (c *Caches) Stop() { func (c *Caches) Stop() {

View file

@ -1,39 +0,0 @@
// GoToSocial
// Copyright (C) GoToSocial Authors admin@gotosocial.org
// SPDX-License-Identifier: AGPL-3.0-or-later
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package config
import (
"net/netip"
"github.com/superseriousbusiness/gotosocial/internal/log"
)
func MustParseIPPrefixes(in []string) []netip.Prefix {
prefs := make([]netip.Prefix, 0, len(in))
for _, i := range in {
pref, err := netip.ParsePrefix(i)
if err != nil {
log.Panicf(nil, "error parsing ip prefix from %q: %v", i, err)
}
prefs = append(prefs, pref)
}
return prefs
}

View file

@ -44,6 +44,11 @@ func (sch *Scheduler) Start() bool {
return false return false
} }
// Started returns true if the scheduler has been started.
func (sch *Scheduler) Started() bool {
return sch.ts != nil
}
// Stop attempts to stop scheduler, cancelling // Stop attempts to stop scheduler, cancelling
// all running tasks. Returns false if not running. // all running tasks. Returns false if not running.
func (sch *Scheduler) Stop() bool { func (sch *Scheduler) Stop() bool {

View file

@ -24,11 +24,11 @@ import (
"math/rand" "math/rand"
"net" "net"
"net/http" "net/http"
"net/netip"
"strconv" "strconv"
"strings" "strings"
"testing" "testing"
"github.com/superseriousbusiness/gotosocial/internal/config"
"github.com/superseriousbusiness/gotosocial/internal/httpclient" "github.com/superseriousbusiness/gotosocial/internal/httpclient"
"github.com/superseriousbusiness/gotosocial/internal/queue" "github.com/superseriousbusiness/gotosocial/internal/queue"
"github.com/superseriousbusiness/gotosocial/internal/transport/delivery" "github.com/superseriousbusiness/gotosocial/internal/transport/delivery"
@ -44,11 +44,8 @@ func TestDeliveryWorkerPool(t *testing.T) {
func testDeliveryWorkerPool(t *testing.T, sz int, input []*testrequest) { func testDeliveryWorkerPool(t *testing.T, sz int, input []*testrequest) {
wp := new(delivery.WorkerPool) wp := new(delivery.WorkerPool)
wp.Init(httpclient.New(httpclient.Config{ allowLocal := []netip.Prefix{netip.MustParsePrefix("127.0.0.0/8")}
AllowRanges: config.MustParseIPPrefixes([]string{ wp.Init(httpclient.New(httpclient.Config{AllowRanges: allowLocal}))
"127.0.0.0/8",
}),
}))
wp.Start(sz) wp.Start(sz)
defer wp.Stop() defer wp.Stop()
test(t, &wp.Queue, input) test(t, &wp.Queue, input)