fix-2
All checks were successful
release-tag / release-image (push) Successful in 1m26s

This commit is contained in:
2025-09-30 00:34:24 +02:00
parent b3c1f37632
commit 42b0493adb
2 changed files with 16 additions and 12 deletions

View File

@@ -59,6 +59,8 @@ func loadConfig() AppConfig {
m.HelloInterval = parseDuration(os.Getenv("MESH_HELLO_INTERVAL"), 20*time.Second) m.HelloInterval = parseDuration(os.Getenv("MESH_HELLO_INTERVAL"), 20*time.Second)
m.HelloFanout = parseIntEnv(os.Getenv("MESH_HELLO_FANOUT"), 8) m.HelloFanout = parseIntEnv(os.Getenv("MESH_HELLO_FANOUT"), 8)
m.BlobTimeout = parseDuration(os.Getenv("MESH_BLOB_TIMEOUT"), 0)
// Wenn keine AdvertURL gesetzt ist, versuche eine sinnvolle Herleitung: // Wenn keine AdvertURL gesetzt ist, versuche eine sinnvolle Herleitung:
if strings.TrimSpace(m.AdvertURL) == "" { if strings.TrimSpace(m.AdvertURL) == "" {
m.AdvertURL = inferAdvertURL(m.BindAddr) m.AdvertURL = inferAdvertURL(m.BindAddr)

View File

@@ -41,6 +41,8 @@ type Config struct {
// NEU: // NEU:
HelloInterval time.Duration // wie oft pingen HelloInterval time.Duration // wie oft pingen
HelloFanout int // wie viele Peers pro Tick HelloFanout int // wie viele Peers pro Tick
BlobTimeout time.Duration
} }
type Peer struct { type Peer struct {
@@ -714,31 +716,31 @@ func (n *Node) blobHandler(w http.ResponseWriter, r *http.Request) {
// sendBlobRequest schickt eine signierte Anfrage an /mesh/blob und liefert die Response // sendBlobRequest schickt eine signierte Anfrage an /mesh/blob und liefert die Response
// zurück (Caller MUSS resp.Body schließen!). Bei HTTP 200 wird der Peer als gesehen markiert. // zurück (Caller MUSS resp.Body schließen!). Bei HTTP 200 wird der Peer als gesehen markiert.
func (n *Node) sendBlobRequest(url, id string) (*http.Response, error) { func (n *Node) sendBlobRequest(url, id string) (*http.Response, error) {
body, _ := json.Marshal(struct { b, _ := json.Marshal(struct {
ID string `json:"id"` ID string `json:"id"`
}{ID: id}) }{ID: id})
req, _ := http.NewRequest(http.MethodPost, strings.TrimRight(url, "/")+"/mesh/blob", bytes.NewReader(body)) req, _ := http.NewRequest(http.MethodPost, strings.TrimRight(url, "/")+"/mesh/blob", bytes.NewReader(b))
req.Header.Set("X-Mesh-Sig", n.sign(body)) req.Header.Set("X-Mesh-Sig", n.sign(b))
req.Header.Set("Content-Type", "application/json") req.Header.Set("Content-Type", "application/json")
// kurzer Timeout für Blob-Requests (anpassbar) // ❗ WICHTIG: kein kurzer Timeout. Optional: großer Timeout aus Config
ctx, cancel := context.WithTimeout(context.Background(), 8*time.Second) ctx := context.Background()
defer cancel() if n.cfg.BlobTimeout > 0 {
var cancel context.CancelFunc
ctx, cancel = context.WithTimeout(context.Background(), n.cfg.BlobTimeout)
defer cancel()
}
req = req.WithContext(ctx) req = req.WithContext(ctx)
resp, err := n.client.Do(req) resp, err := n.client.Do(req)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// OK → Peer als "gesehen" markieren und Response (für Streaming) zurückgeben
if resp.StatusCode == http.StatusOK { if resp.StatusCode == http.StatusOK {
n.touchPeer(url) n.touchPeer(url) // ausgehender Erfolg zählt als "gesehen"
return resp, nil // Caller liest/streamt Body und schließt ihn return resp, nil
} }
// Nicht-OK → Body leeren/schließen und Fehler zurück
io.Copy(io.Discard, resp.Body) io.Copy(io.Discard, resp.Body)
resp.Body.Close() resp.Body.Close()
return nil, fmt.Errorf("blob %s from %s: %s", id, url, resp.Status) return nil, fmt.Errorf("blob %s from %s: %s", id, url, resp.Status)