Files
webui4frpc/internal/cluster/ring_handler.go

72 lines
1.8 KiB
Go

// Runtime handlers the ring engine needs, provided by the app:
// - RuntimeLoad: sample this node's memory/network load;
// - Claim: create the frpc worker/forward for a claimed task.
package cluster
import (
"context"
"os"
"runtime"
)
// AppHandler is the app-provided bridge for ring load sampling + task claims.
type AppHandler struct {
// LoadFn returns (mem%, net%) — lower is more idle.
LoadFn func() (memPct, netPct float64)
// ClaimFn creates the forward on this node (persist + spawn worker).
ClaimFn func(ctx context.Context, tk *Task) error
// RevokeFn cancels the forward on this node (stop worker + drop from store).
RevokeFn func(ctx context.Context, tk *Task) error
}
// RuntimeLoad implements Handler.
func (a *AppHandler) RuntimeLoad() Load {
mem, net := 0.0, 0.0
if a.LoadFn != nil {
mem, net = a.LoadFn()
}
return Load{MemPct: mem, NetPct: net}
}
// Claim implements Handler.
func (a *AppHandler) Claim(ctx context.Context, tk *Task) error {
if a.ClaimFn == nil {
return nil
}
return a.ClaimFn(ctx, tk)
}
// Revoke implements Handler.
func (a *AppHandler) Revoke(ctx context.Context, tk *Task) error {
if a.RevokeFn == nil {
return nil
}
return a.RevokeFn(ctx, tk)
}
// SampleMemLoad returns a cheap memory-usage percentage (0..100).
func SampleMemLoad() float64 {
var m runtime.MemStats
runtime.ReadMemStats(&m)
total := m.Sys
if total == 0 {
return 0
}
return float64(m.Alloc) / float64(total) * 100
}
// SampleNetLoad is an approximation: bytes in/out relative to a soft budget.
// Kept simple; production could use /proc/net/dev deltas.
func SampleNetLoad() float64 {
return 0
}
// HostID returns a stable node id (hostname; empty fallback to pid).
func HostID() string {
h, _ := os.Hostname()
if h == "" {
return "node"
}
return h
}