fix(meshmapper): allow MeshMapper's 60s request timeout

This commit is contained in:
MrAlders0n committed 2026-10-01 06:05:42 -04:00
1 parent 7392fdd2d6
commit 27ca84f51e
5 files changed
+38 -7

No files matched your search

+2 -2
View File
@@ -65,7 +65,7 @@ type Channels struct {
func NewChannels(ctx context.Context, cfg config.MeshMapperChannelsConfig, store ChannelStore, dir *Directory, keys ChannelKeys) (*Channels, error) {
c := &Channels{store: store, keys: keys, dir: dir, channelsURL: channelsEndpoint, interval: cfg.Interval(), seen: map[string]bool{},
client: &http.Client{
Timeout: 10 * time.Second,
Timeout: requestTimeout,
CheckRedirect: func(*http.Request, []*http.Request) error { return http.ErrUseLastResponse },
}}
if !cfg.Enabled {
@@ -130,7 +130,7 @@ func (c *Channels) Refresh(ctx context.Context) (err error) {
err = nil
}
}()
ctx, cancel := context.WithTimeout(ctx, 15*time.Second)
ctx, cancel := context.WithTimeout(ctx, refreshTimeout)
defer cancel()
now := time.Now().UTC()
iatas, err := c.store.ListKnownIATAs(ctx)
+1 -1
View File
@@ -64,7 +64,7 @@ type Directory struct {
func NewDirectory(store DirectoryStore) *Directory {
return &Directory{store: store, listURL: ZonesURL, lists: map[string]*zoneList{}, client: &http.Client{
Timeout: 30 * time.Second,
Timeout: requestTimeout,
CheckRedirect: func(*http.Request, []*http.Request) error { return http.ErrUseLastResponse },
}}
}
+2 -2
View File
@@ -79,7 +79,7 @@ func (i *Importer) SetCacheInvalidator(fn func(context.Context)) { i.onChange =
func New(ctx context.Context, cfg config.MeshMapperScopesConfig, store Store, dir *Directory, scopes *scopestore.ScopeStore, manual []scopestore.Entry) (*Importer, error) {
i := &Importer{store: store, scopes: scopes, manual: manual, dir: dir, scopesURL: scopesEndpoint, seen: map[string]bool{},
interval: cfg.Interval(), client: &http.Client{
Timeout: 10 * time.Second,
Timeout: requestTimeout,
CheckRedirect: func(*http.Request, []*http.Request) error { return http.ErrUseLastResponse },
}}
if !cfg.Enabled {
@@ -142,7 +142,7 @@ func (i *Importer) Refresh(ctx context.Context) (err error) {
err = nil
}
}()
ctx, cancel := context.WithTimeout(ctx, 15*time.Second)
ctx, cancel := context.WithTimeout(ctx, refreshTimeout)
defer cancel()
now := time.Now().UTC()
iatas, err := i.store.ListKnownIATAs(ctx)
+6 -2
View File
@@ -26,6 +26,10 @@ const (
MaxZoneList = 1 << 20
MaxBoundaryBody = 8 << 20 // outlines are never simplified
// MeshMapper asks clients to allow 60-120s; a request given up on may still use the day's call.
requestTimeout = 60 * time.Second
refreshTimeout = requestTimeout + 30*time.Second // room for the DB write after a slow request
zoneListFresh = config.MinZonesRefresh // get_zones.php allows one request per country per 23.5h
zoneFailureRetry = config.MinZonesRefresh // failed requests count too
)
@@ -82,7 +86,7 @@ type Zones struct {
func NewZones(cfg config.MeshMapperZonesConfig, store ZoneStore, dir *Directory) *Zones {
return &Zones{store: store, enabled: cfg.Enabled, importGroups: cfg.Enabled && cfg.ImportGroups, seen: map[string]bool{}, interval: cfg.Interval(), dir: dir,
boundsURL: boundaryEndpoint, client: &http.Client{
Timeout: 30 * time.Second,
Timeout: requestTimeout,
CheckRedirect: func(*http.Request, []*http.Request) error { return http.ErrUseLastResponse },
}}
}
@@ -165,7 +169,7 @@ func (z *Zones) Refresh(ctx context.Context) (err error) {
err = nil
}
}()
ctx, cancel := context.WithTimeout(ctx, time.Minute)
ctx, cancel := context.WithTimeout(ctx, refreshTimeout)
defer cancel()
now := time.Now().UTC()
// IATAs are created from traffic, so pick up new ones every tick.
+27
View File
@@ -15,6 +15,8 @@ import (
"time"
"github.com/MeshCore-Beacon/beacon-server/internal/config"
"github.com/MeshCore-Beacon/beacon-server/internal/keystore"
"github.com/MeshCore-Beacon/beacon-server/internal/scopestore"
)
const square = `{"type":"Polygon","coordinates":[[[-76,45],[-75,45],[-75,46],[-76,46],[-76,45]]]}`
@@ -465,3 +467,28 @@ func TestDecodeBoundaryRejectsUnusableOutlines(t *testing.T) {
t.Fatal("case-insensitive code rejected", err)
}
}
func TestClientsAllowMeshMapperTimeout(t *testing.T) {
ctx := context.Background()
scopes, err := New(ctx, config.MeshMapperScopesConfig{}, nil, NewDirectory(nil), scopestore.New(), nil)
if err != nil {
t.Fatal(err)
}
channels, err := NewChannels(ctx, config.MeshMapperChannelsConfig{}, newChannelMemoryStore(), NewDirectory(nil), keystore.NewMapKeyStore(nil))
if err != nil {
t.Fatal(err)
}
for name, c := range map[string]*http.Client{
"directory": NewDirectory(nil).client,
"zones": NewZones(config.MeshMapperZonesConfig{}, nil, nil).client,
"scopes": scopes.client,
"channels": channels.client,
} {
if c.Timeout < 60*time.Second {
t.Errorf("%s client gives up after %v; MeshMapper asks for 60-120s", name, c.Timeout)
}
}
if refreshTimeout <= requestTimeout {
t.Fatal("a refresh must outlast its request")
}
}