Skip to content

Commit 6e9e267

Browse files
committed
ipn/yegor: retry for set/get dns filters
1 parent 3cce7f0 commit 6e9e267

1 file changed

Lines changed: 122 additions & 55 deletions

File tree

intra/ipn/rpn/yegor.go

Lines changed: 122 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ const (
130130
maxPerRegionWgConfs = 4
131131
maxAnyWgConfs = 8
132132
wsMaxPermaWgKeys = 5
133+
maxDNSSyncTries = 2
133134

134135
disablePermaCreds = true
135136

@@ -2520,45 +2521,80 @@ func listKeys(h *http.Client, ent *WsEntitlement, bearer string) (*WsWgListKeysR
25202521
}
25212522

25222523
// getDNSFilters returns the current DNS filter list.
2524+
// retried [maxDNSSyncTries] times after random wait > 1s (but less than 2s).
25232525
func getDNSFilters(h *http.Client, ent *WsEntitlement, bearer string) ([]WsFilter, error) {
25242526
if len(bearer) <= 0 {
25252527
return nil, errWsNoToken
25262528
}
25272529
tokst := tokenState(bearer)
2530+
2531+
minwait := 1000 // ms
2532+
maxjitter := 1000 // ms
2533+
25282534
u := baseurl(ent.TestDomain, ent.Cid).JoinPath(wsgetfilterspath)
2529-
req, err := http.NewRequest("GET", u.String(), nil)
2530-
if err != nil {
2531-
return nil, log.EE("ws: filters: get: req err: %v", err)
2532-
}
2533-
authHeader(req, bearer)
2534-
didAndDBHeader(req, ent.Did, ent.DidToken, ent.TestDomain)
2535+
for t := range maxDNSSyncTries {
2536+
canretry := t < maxDNSSyncTries-1
2537+
wait := time.Duration(minwait+rand.IntN(maxjitter)) * time.Millisecond
25352538

2536-
if log.Verbose {
2537-
log.V("ws: filters: get: req: %s tok %s", u.String(), tokst)
2538-
}
2539+
req, err := http.NewRequest("GET", u.String(), nil)
2540+
if err != nil {
2541+
return nil, log.EE("ws: filters: get: req err: %v", err)
2542+
}
2543+
authHeader(req, bearer)
2544+
didAndDBHeader(req, ent.Did, ent.DidToken, ent.TestDomain)
25392545

2540-
res, err := h.Do(req)
2541-
if err != nil || res == nil {
2542-
return nil, log.EE("ws: filters: get: do err (nil? %t / tok? %s): %v", res == nil, tokst, err)
2543-
}
2544-
defer core.Close(res.Body)
2545-
updateDidTokenIfNeeded(ent, res)
2546-
if res.StatusCode != http.StatusOK {
2547-
return nil, wsErr(res, "getrob/"+tokst)
2548-
}
2546+
if log.Verbose {
2547+
log.V("ws: filters: get: (#%d) req: %s tok %s", t, u.String(), tokst)
2548+
}
25492549

2550-
var out WsFiltersResponse
2551-
if _, err = wsRes(res, &out, "getrob/"+tokst); err != nil {
2552-
return nil, err
2553-
}
2554-
if len(out.Data.Filters) <= 0 {
2555-
return nil, log.EE("ws: filters: get: %v; tok? %s", errWsNoFilters, tokst)
2556-
}
2557-
log.I("ws: filters: get: ok (tok? %s); %d filters", tokst, len(out.Data.Filters))
2558-
return out.Data.Filters, nil
2550+
res, err := h.Do(req)
2551+
if err != nil || res == nil {
2552+
if canretry {
2553+
log.W("ws: filters: get: (#%d) do err (nil? %t / tok? %s): %v; retry in %s",
2554+
t, res == nil, tokst, err, core.FmtPeriod(wait))
2555+
time.Sleep(wait)
2556+
continue
2557+
}
2558+
return nil, log.EE("ws: filters: get: (#%d) do err (nil? %t / tok? %s): %v", t, res == nil, tokst, err)
2559+
}
2560+
updateDidTokenIfNeeded(ent, res)
2561+
if res.StatusCode != http.StatusOK {
2562+
if canretry {
2563+
core.Close(res.Body)
2564+
log.W("ws: filters: get: (#%d) (%d) retry in %s; tok? %s",
2565+
t, res.StatusCode, core.FmtPeriod(wait), tokst)
2566+
time.Sleep(wait)
2567+
continue
2568+
}
2569+
err2 := wsErr(res, "getfilter/"+tokst)
2570+
core.Close(res.Body)
2571+
return nil, err2
2572+
}
2573+
2574+
var out WsFiltersResponse
2575+
_, err = wsRes(res, &out, "getfilter/"+tokst)
2576+
core.Close(res.Body)
2577+
if err != nil {
2578+
return nil, err // no retry
2579+
}
2580+
2581+
if len(out.Data.Filters) <= 0 {
2582+
if canretry {
2583+
log.W("ws: filters: get: (#%d) empty filters retry in %s; tok? %s", t, core.FmtPeriod(wait), tokst)
2584+
time.Sleep(wait)
2585+
continue
2586+
}
2587+
return nil, log.EE("ws: filters: get: (#%d) %v; tok? %s", t, errWsNoFilters, tokst)
2588+
}
2589+
log.I("ws: filters: get: (#%d) ok (tok? %s); %d filters", t, tokst, len(out.Data.Filters))
2590+
return out.Data.Filters, nil
2591+
} // else: maxDNSSyncTries not set or exceeded?
2592+
2593+
return nil, log.EE("ws: filters: get: unreachable; tok? %s", tokst)
25592594
}
25602595

25612596
// setDNSFilter enables or disables on a DNS filterID.
2597+
// retried [maxDNSSyncTries] times after random wait > 1s (but less than 2s).
25622598
func setDNSFilter(h *http.Client, ent *WsEntitlement, bearer, filterID string, enable bool) error {
25632599
if len(bearer) <= 0 {
25642600
return errWsNoToken
@@ -2573,38 +2609,69 @@ func setDNSFilter(h *http.Client, ent *WsEntitlement, bearer, filterID string, e
25732609
return log.EE("ws: filters: set: marshal err: %v", err)
25742610
}
25752611

2612+
minwait := 1000 // ms
2613+
maxjitter := 1000 // ms
2614+
25762615
u := baseurl(ent.TestDomain, ent.Cid).JoinPath(wssetfilterpath)
2577-
req, err := http.NewRequest("PUT", u.String(), strings.NewReader(string(body)))
2578-
if err != nil {
2579-
return log.EE("ws: filters: set: req err: %v", err)
2580-
}
2581-
req.Header.Set("Content-Type", "application/json")
2582-
authHeader(req, bearer)
2583-
didAndDBHeader(req, ent.Did, ent.DidToken, ent.TestDomain)
2616+
for t := range maxDNSSyncTries {
2617+
canretry := t < maxDNSSyncTries-1
2618+
wait := time.Duration(minwait+rand.IntN(maxjitter)) * time.Millisecond
25842619

2585-
if log.Verbose {
2586-
log.V("ws: filters: set: %s status=%d req: %s tok %s", filterID, status, u.String(), tokst)
2587-
}
2620+
req, err := http.NewRequest("PUT", u.String(), strings.NewReader(string(body)))
2621+
if err != nil {
2622+
return log.EE("ws: filters: set: req err: %v", err)
2623+
}
2624+
req.Header.Set("Content-Type", "application/json")
2625+
authHeader(req, bearer)
2626+
didAndDBHeader(req, ent.Did, ent.DidToken, ent.TestDomain)
25882627

2589-
res, err := h.Do(req)
2590-
if err != nil || res == nil {
2591-
return log.EE("ws: filters: set: do err (nil? %t / tok? %s): %v", res == nil, tokst, err)
2592-
}
2593-
defer core.Close(res.Body)
2594-
updateDidTokenIfNeeded(ent, res)
2595-
if res.StatusCode != http.StatusOK {
2596-
return wsErr(res, "setrob("+filterID+")/"+tokst)
2597-
}
2628+
if log.Verbose {
2629+
log.V("ws: filters: set: (#%d) %s status=%d req: %s tok %s", t, filterID, status, u.String(), tokst)
2630+
}
25982631

2599-
var out WsFilterSetResponse
2600-
if _, err = wsRes(res, &out, "setrob("+filterID+")/"+tokst); err != nil {
2601-
return err
2602-
}
2603-
if out.Data.Success != 1 {
2604-
return log.EE("ws: filters: set: %s status=%d success!=1; tok? %s", filterID, status, tokst)
2605-
}
2606-
log.I("ws: filters: set: ok %s status=%d (tok? %s)", filterID, status, tokst)
2607-
return nil
2632+
res, err := h.Do(req)
2633+
if err != nil || res == nil {
2634+
if canretry {
2635+
log.W("ws: filters: set: (#%d) do err (nil? %t / tok? %s): %v; retry in %s",
2636+
t, res == nil, tokst, err, core.FmtPeriod(wait))
2637+
time.Sleep(wait)
2638+
continue
2639+
}
2640+
return log.EE("ws: filters: set: (#%d) do err (nil? %t / tok? %s): %v", t, res == nil, tokst, err)
2641+
}
2642+
updateDidTokenIfNeeded(ent, res)
2643+
if res.StatusCode != http.StatusOK {
2644+
if canretry {
2645+
core.Close(res.Body)
2646+
log.W("ws: filters: set: (#%d) %s status=%d (%d) retry in %s; tok? %s",
2647+
t, filterID, status, res.StatusCode, core.FmtPeriod(wait), tokst)
2648+
time.Sleep(wait)
2649+
continue
2650+
}
2651+
err2 := wsErr(res, "setrob("+filterID+")/"+tokst)
2652+
core.Close(res.Body)
2653+
return err2
2654+
}
2655+
2656+
var out WsFilterSetResponse
2657+
_, err = wsRes(res, &out, "setrob("+filterID+")/"+tokst)
2658+
core.Close(res.Body)
2659+
if err != nil {
2660+
return err // no retry
2661+
}
2662+
if out.Data.Success != 1 {
2663+
if canretry {
2664+
log.W("ws: filters: set: (#%d) %s status=%d success!=1 retry in %s; tok? %s", t, filterID, status, core.FmtPeriod(wait), tokst)
2665+
time.Sleep(wait)
2666+
continue
2667+
}
2668+
return log.EE("ws: filters: set: (#%d) %s status=%d success!=1; tok? %s", t, filterID, status, tokst)
2669+
}
2670+
log.I("ws: filters: set: (#%d) ok %s status=%d (tok? %s)", t, filterID, status, tokst)
2671+
return nil
2672+
} // else: maxDNSSyncTries not set or exceeded?
2673+
2674+
return log.EE("ws: filters: set: %s status=%d unreachable; tok? %s", filterID, status, tokst)
26082675
}
26092676

26102677
// syncDNSFilters reconciles the Robert DNS filters on the server with the desired state

0 commit comments

Comments
 (0)