mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-05-24 02:31:28 +00:00
CP13-8 scenario results on m01/M02 (25Gbps RoCE): fsck_ext4: CLEAN file count: 200 (assert_equal PASS) checksum match: MATCH (assert_contains PASS) pgbench TPS: 565.69 (assert_greater PASS) auto-failover: 10.0.0.1:18480 → 10.0.0.3:18480 Code changes (tester + scenario): - volume_server_block.go: readiness state, assignment lifecycle cleanup - block_heartbeat_loop.go: readiness-aware heartbeat reporting - store_blockvol.go: readiness tracking - master_server_handlers_block.go: block API handler updates - cp13-8-real-workload-validation.yaml: redesigned scenario (removed block_promote, use natural auto-failover flow, bootstrap write before wait_volume_healthy) - testrunner/actions/devops.go: scenario action improvements - replica_read_test.go: component-level replica read test Phase docs: CP13-7 accepted, CP13-8/8A technical packs updated, design docs updated for protocol closure evidence. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
91 lines
3.0 KiB
Go
91 lines
3.0 KiB
Go
package weed_server
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/seaweedfs/seaweedfs/weed/storage/blockvol"
|
|
)
|
|
|
|
// ShipperDebugInfo is the real-time shipper state for one replica.
|
|
type ShipperDebugInfo struct {
|
|
DataAddr string `json:"data_addr"`
|
|
State string `json:"state"`
|
|
FlushedLSN uint64 `json:"flushed_lsn"`
|
|
}
|
|
|
|
// BlockVolumeDebugInfo is the real-time block volume state.
|
|
type BlockVolumeDebugInfo struct {
|
|
Path string `json:"path"`
|
|
Role string `json:"role"`
|
|
Epoch uint64 `json:"epoch"`
|
|
HeadLSN uint64 `json:"head_lsn"`
|
|
Degraded bool `json:"degraded"`
|
|
RoleApplied bool `json:"role_applied"`
|
|
ReceiverReady bool `json:"receiver_ready"`
|
|
ShipperConfigured bool `json:"shipper_configured"`
|
|
ShipperConnected bool `json:"shipper_connected"`
|
|
ReplicaEligible bool `json:"replica_eligible"`
|
|
PublishHealthy bool `json:"publish_healthy"`
|
|
Shippers []ShipperDebugInfo `json:"shippers,omitempty"`
|
|
Timestamp string `json:"timestamp"`
|
|
}
|
|
|
|
// debugBlockShipperHandler returns real-time shipper state for all block volumes.
|
|
// Unlike the master's replica_degraded (heartbeat-lagged), this reads directly
|
|
// from the shipper's atomic state field — no heartbeat delay.
|
|
//
|
|
// GET /debug/block/shipper
|
|
func (vs *VolumeServer) debugBlockShipperHandler(w http.ResponseWriter, r *http.Request) {
|
|
if vs.blockService == nil {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
json.NewEncoder(w).Encode([]BlockVolumeDebugInfo{})
|
|
return
|
|
}
|
|
|
|
store := vs.blockService.Store()
|
|
if store == nil {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
json.NewEncoder(w).Encode([]BlockVolumeDebugInfo{})
|
|
return
|
|
}
|
|
|
|
var infos []BlockVolumeDebugInfo
|
|
store.IterateBlockVolumes(func(path string, vol *blockvol.BlockVol) {
|
|
status := vol.Status()
|
|
readiness := vs.blockService.ReadinessSnapshot(path)
|
|
info := BlockVolumeDebugInfo{
|
|
Path: path,
|
|
Role: status.Role.String(),
|
|
Epoch: status.Epoch,
|
|
HeadLSN: status.WALHeadLSN,
|
|
Degraded: status.ReplicaDegraded,
|
|
RoleApplied: readiness.RoleApplied,
|
|
ReceiverReady: readiness.ReceiverReady,
|
|
ShipperConfigured: readiness.ShipperConfigured,
|
|
ShipperConnected: readiness.ShipperConnected,
|
|
ReplicaEligible: readiness.ReplicaEligible,
|
|
PublishHealthy: readiness.PublishHealthy,
|
|
Timestamp: time.Now().UTC().Format(time.RFC3339Nano),
|
|
}
|
|
|
|
// Get per-shipper state from ShipperGroup if available.
|
|
sg := vol.GetShipperGroup()
|
|
if sg != nil {
|
|
for _, ss := range sg.ShipperStates() {
|
|
info.Shippers = append(info.Shippers, ShipperDebugInfo{
|
|
DataAddr: ss.DataAddr,
|
|
State: ss.State,
|
|
FlushedLSN: ss.FlushedLSN,
|
|
})
|
|
}
|
|
}
|
|
|
|
infos = append(infos, info)
|
|
})
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
json.NewEncoder(w).Encode(infos)
|
|
}
|