This commit is contained in:
@@ -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)
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user