feat(component-failover-adoption): route apiserver's candidate parsing through the real C parser
Replaces apiserver's hand-written Go parsePeer() with a CGO wrapper around the shared C parser+validator pair (xce_parse_peers then xce_cluster_config_validate, both src/lib/cluster.c) that worker and scheduler already use from their own main.c's. Gives apiserver the same [name=]host:port[,...] syntax (including the name= prefix the old Go parser could not express) and identical malformed-candidate rejection (empty host, port <= 0, non-numeric port) -- round-1 review caught the first pass skipping the validate() half, silently accepting inputs worker/scheduler both reject. A malformed entry now rejects the whole candidate list rather than being skipped with a warning (matches xce_parse_peers()'s own all-or-nothing construction and worker/scheduler's precedent) -- surfaced loudly via RegisterToBackend's error, not silently. Parsing only -- RegisterToBackend()'s connect loop and tryConnect() are unchanged; collapsing them into a single connect call is task 4.2's job. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NNB4zGPCsHyDUCDJyMbiQN
This commit is contained in:
parent
d383d04311
commit
8b1e13a52b
7 changed files with 262 additions and 134 deletions
|
|
@ -59,6 +59,7 @@ import (
|
|||
logger "apiserver/utils"
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
"unsafe"
|
||||
|
||||
|
|
@ -114,22 +115,27 @@ func RegisterToBackend(config *BackendConfig) error {
|
|||
}
|
||||
|
||||
if len(config.Peers) > 0 {
|
||||
// Parsing is routed through the same C parser (xce_parse_peers) worker
|
||||
// and scheduler already call directly -- Req 6.1/6.2. A malformed
|
||||
// entry rejects the whole candidate list up front (matching
|
||||
// worker's/scheduler's own all-or-nothing --peers parsing) rather
|
||||
// than being skipped with a warning as the old hand-written
|
||||
// parsePeer()-per-entry loop did.
|
||||
candidates, err := parseCandidates(strings.Join(config.Peers, ","))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var lastErr error
|
||||
for _, peer := range config.Peers {
|
||||
host, port, err := parsePeer(peer)
|
||||
if err != nil {
|
||||
logger.Warn("Skipping invalid peer", zap.String("peer", peer), zap.Error(err))
|
||||
lastErr = err
|
||||
continue
|
||||
}
|
||||
if err := tryConnect(host, port, from, key); err != nil {
|
||||
for _, cand := range candidates {
|
||||
if err := tryConnect(cand.Host, cand.Port, from, key); err != nil {
|
||||
logger.Warn("Candidate unreachable, trying next",
|
||||
zap.String("host", host), zap.Int("port", port), zap.Error(err))
|
||||
zap.String("host", cand.Host), zap.Int("port", cand.Port), zap.Error(err))
|
||||
lastErr = err
|
||||
continue
|
||||
}
|
||||
logger.Info("Backend connection established (HA)",
|
||||
zap.String("host", host), zap.Int("port", port))
|
||||
zap.String("host", cand.Host), zap.Int("port", cand.Port))
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("all HA candidates failed: %w", lastErr)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue