131 lines
3.7 KiB
Go
131 lines
3.7 KiB
Go
package mesh
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strings"
|
|
"sync/atomic"
|
|
"time"
|
|
|
|
"github.com/example/remote-access-platform/agents/rap-node-agent/internal/fabricproto"
|
|
)
|
|
|
|
type FabricOverlayTransportConfig struct {
|
|
ClusterID string
|
|
LocalNodeID string
|
|
RouterConfig FabricChannelRouterConfig
|
|
Timeout time.Duration
|
|
}
|
|
|
|
type FabricOverlayTransport struct {
|
|
Runtime *FabricChannelRuntime
|
|
RouteSets map[string]FabricRouteSet
|
|
Config FabricOverlayTransportConfig
|
|
sequence atomic.Uint64
|
|
}
|
|
|
|
type FabricOverlayTransportSnapshot struct {
|
|
RoutePressure FabricRoutePressureSnapshot `json:"route_pressure"`
|
|
RouteHealth FabricRouteHealthSnapshot `json:"route_health,omitempty"`
|
|
}
|
|
|
|
type FabricOverlaySendRequest struct {
|
|
ChannelID string
|
|
TargetKind FabricChannelTargetKind
|
|
TargetID string
|
|
TrafficClass fabricproto.TrafficClass
|
|
Payloads [][]byte
|
|
StickyKey string
|
|
}
|
|
|
|
func NewFabricOverlayTransport(transport FabricTransport, routeSets map[string]FabricRouteSet, cfg FabricOverlayTransportConfig) *FabricOverlayTransport {
|
|
if cfg.Timeout <= 0 {
|
|
cfg.Timeout = 30 * time.Second
|
|
}
|
|
runtime := NewFabricChannelRuntime(transport, FabricChannelRuntimeConfig{
|
|
RouterConfig: cfg.RouterConfig,
|
|
Timeout: cfg.Timeout,
|
|
})
|
|
normalized := make(map[string]FabricRouteSet, len(routeSets))
|
|
for targetID, routeSet := range routeSets {
|
|
targetID = strings.TrimSpace(targetID)
|
|
if targetID != "" {
|
|
normalized[targetID] = routeSet
|
|
}
|
|
}
|
|
return &FabricOverlayTransport{
|
|
Runtime: runtime,
|
|
RouteSets: normalized,
|
|
Config: cfg,
|
|
}
|
|
}
|
|
|
|
func (t *FabricOverlayTransport) Send(ctx context.Context, req FabricOverlaySendRequest) (FabricChannelRuntimeResult, error) {
|
|
if t == nil || t.Runtime == nil {
|
|
return FabricChannelRuntimeResult{}, ErrForwardRuntimeUnavailable
|
|
}
|
|
targetID := strings.TrimSpace(req.TargetID)
|
|
if targetID == "" {
|
|
return FabricChannelRuntimeResult{}, ErrFabricChannelInvalid
|
|
}
|
|
routeSet, ok := t.RouteSets[targetID]
|
|
if !ok {
|
|
return FabricChannelRuntimeResult{}, ErrFabricRouteNotFound
|
|
}
|
|
targetKind := req.TargetKind
|
|
if targetKind == "" {
|
|
targetKind = routeSet.TargetKind
|
|
}
|
|
if targetKind == "" {
|
|
targetKind = FabricChannelTargetNode
|
|
}
|
|
trafficClass := req.TrafficClass
|
|
if trafficClass == 0 {
|
|
trafficClass = fabricproto.TrafficClassReliable
|
|
}
|
|
t.Runtime.Config.TrafficClass = trafficClass
|
|
spec := FabricChannelSpec{
|
|
ChannelID: firstNonEmpty(strings.TrimSpace(req.ChannelID), fmt.Sprintf("fabric-overlay-%d", t.sequence.Add(1))),
|
|
ClusterID: strings.TrimSpace(t.Config.ClusterID),
|
|
SourceNodeID: strings.TrimSpace(t.Config.LocalNodeID),
|
|
TargetKind: targetKind,
|
|
TargetID: targetID,
|
|
TrafficClass: loadFabricTrafficClassName(trafficClass),
|
|
StickyKey: strings.TrimSpace(req.StickyKey),
|
|
CreatedAt: time.Now().UTC(),
|
|
}
|
|
return t.Runtime.SendReliable(ctx, spec, routeSet, req.Payloads)
|
|
}
|
|
|
|
func (t *FabricOverlayTransport) SnapshotPressure() FabricRoutePressureSnapshot {
|
|
if t == nil || t.Runtime == nil || t.Runtime.Pressure == nil {
|
|
return FabricRoutePressureSnapshot{}
|
|
}
|
|
return t.Runtime.Pressure.SnapshotPressure()
|
|
}
|
|
|
|
func (t *FabricOverlayTransport) Snapshot() FabricOverlayTransportSnapshot {
|
|
if t == nil || t.Runtime == nil {
|
|
return FabricOverlayTransportSnapshot{}
|
|
}
|
|
return FabricOverlayTransportSnapshot{
|
|
RoutePressure: t.Runtime.snapshotRoutePressure(),
|
|
RouteHealth: t.Runtime.snapshotRouteHealth(),
|
|
}
|
|
}
|
|
|
|
func loadFabricTrafficClassName(trafficClass fabricproto.TrafficClass) string {
|
|
switch trafficClass {
|
|
case fabricproto.TrafficClassControl:
|
|
return "control"
|
|
case fabricproto.TrafficClassInteractive:
|
|
return "interactive"
|
|
case fabricproto.TrafficClassBulk:
|
|
return "bulk"
|
|
case fabricproto.TrafficClassReliable:
|
|
return "reliable"
|
|
default:
|
|
return fmt.Sprintf("traffic_class_%d", trafficClass)
|
|
}
|
|
}
|