Documentation
¶
Overview ¶
grpc/control_server.go
Index ¶
- Constants
- func ComputeSnapshotChecksum(snapshot *pb.ConfigurationSnapshot) (string, error)
- func VerifySnapshotChecksum(snapshot *pb.ConfigurationSnapshot) (bool, error)
- type AppBudgetData
- type BudgetSyncPayload
- type BudgetSyncService
- type Config
- type ControlServer
- func (s *ControlServer) GetEventBus() eventbridge.Bus
- func (s *ControlServer) GetFullConfiguration(ctx context.Context, req *pb.ConfigurationRequest) (*pb.ConfigurationSnapshot, error)
- func (s *ControlServer) LocalStreams() map[string]string
- func (s *ControlServer) RegisterEdge(ctx context.Context, req *pb.EdgeRegistrationRequest) (*pb.EdgeRegistrationResponse, error)
- func (s *ControlServer) SendAnalyticsPulse(ctx context.Context, req *pb.AnalyticsPulse) (*pb.AnalyticsPulseResponse, error)
- func (s *ControlServer) SendHeartbeat(ctx context.Context, req *pb.HeartbeatRequest) (*pb.HeartbeatResponse, error)
- func (s *ControlServer) SendPluginControlBatch(ctx context.Context, req *pb.PluginControlBatch) (*pb.PluginControlBatchResponse, error)
- func (s *ControlServer) SendReload(edgeID, session string, req *pb.ConfigurationReloadRequest) error
- func (s *ControlServer) Serve(listener net.Listener) error
- func (s *ControlServer) SetEdgeBudgetSource(src EdgeBudgetSource)
- func (s *ControlServer) SetEdgePayloadForwarder(f EdgePayloadForwarder)
- func (s *ControlServer) SetGovernedMetadataReader(reader governed_metadata.SnapshotReader)
- func (s *ControlServer) SetPluginManager(manager interface{})
- func (s *ControlServer) SetPushDelivery(p PushDelivery)
- func (s *ControlServer) Start() error
- func (s *ControlServer) Stop()
- func (s *ControlServer) SubscribeToChanges(stream pb.ConfigurationSyncService_SubscribeToChangesServer) error
- func (s *ControlServer) UnregisterEdge(ctx context.Context, req *pb.EdgeUnregistrationRequest) (*emptypb.Empty, error)
- func (s *ControlServer) ValidateToken(ctx context.Context, req *pb.TokenValidationRequest) (*pb.TokenValidationResponse, error)
- type EdgeBudgetSource
- type EdgeInstanceConnection
- type EdgePayloadForwarder
- type EdgePayloadRouter
- type PushDelivery
Constants ¶
const BudgetSyncTopic = eventbridge.BudgetSyncTopic
BudgetSyncTopic is re-exported from eventbridge for backwards compatibility
const DEFAULT_ENCRYPTION_KEY = "DEFAULT_INSECURE_KEY_CHANGE_ME!!"
DEFAULT_ENCRYPTION_KEY is used when MICROGATEWAY_ENCRYPTION_KEY is not set CRITICAL SECURITY WARNING: This MUST be changed in production!
const DefaultBudgetSyncInterval = 30 * time.Second
DefaultBudgetSyncInterval is the default interval for budget sync (30 seconds)
Variables ¶
This section is empty.
Functions ¶
func ComputeSnapshotChecksum ¶
func ComputeSnapshotChecksum(snapshot *pb.ConfigurationSnapshot) (string, error)
ComputeSnapshotChecksum generates a deterministic SHA-256 checksum for a ConfigurationSnapshot. It excludes volatile fields (version, snapshot_time, checksum, timestamps, usage stats) to ensure the checksum only changes when actual configuration data changes.
The checksum is computed from the protobuf-serialized bytes of the snapshot with deterministic marshaling enabled to ensure consistent byte order for maps and repeated fields.
func VerifySnapshotChecksum ¶
func VerifySnapshotChecksum(snapshot *pb.ConfigurationSnapshot) (bool, error)
VerifySnapshotChecksum verifies that a snapshot's checksum matches the computed checksum. Returns true if the checksums match, false otherwise.
Types ¶
type AppBudgetData ¶
type AppBudgetData struct {
// Usage is the current period usage in dollars
Usage float64 `json:"usage"`
// PeriodStart is the start of this app's budget period
PeriodStart time.Time `json:"period_start"`
// PeriodEnd is the end of this app's budget period
PeriodEnd time.Time `json:"period_end"`
}
AppBudgetData contains budget usage and period info for a single app
type BudgetSyncPayload ¶
type BudgetSyncPayload struct {
// AppUsages maps app_id to current period usage in dollars
// Deprecated: Use AppBudgets instead for per-app budget periods
AppUsages map[uint32]float64 `json:"app_usages"`
// AppBudgets maps app_id to budget data with per-app period info
// This supports custom budget_start_date per app
AppBudgets map[uint32]AppBudgetData `json:"app_budgets,omitempty"`
// PeriodStart is the start of the budget period (1st of month)
// Deprecated: Use per-app periods in AppBudgets instead
PeriodStart time.Time `json:"period_start"`
// PeriodEnd is the end of the budget period (last moment of month)
// Deprecated: Use per-app periods in AppBudgets instead
PeriodEnd time.Time `json:"period_end"`
// ControlTimestamp is when the control server generated this payload
// Used by edges to detect clock skew
ControlTimestamp time.Time `json:"control_timestamp"`
// SequenceNumber for ordering and deduplication
SequenceNumber uint64 `json:"sequence_number"`
// Blocks maps app_id to the reason edges must refuse the App on budget
// grounds (Enterprise): its budget is 0, or its hard-blocking team has
// spent its budget. Edges read a synced App budget of 0 as "no limit",
// so this is how a zero budget reaches them. When BlocksIncluded is set
// it is the complete set: edges replace theirs, so a released App is
// served again.
Blocks map[uint32]string `json:"blocks,omitempty"`
BlocksIncluded bool `json:"blocks_included,omitempty"`
}
BudgetSyncPayload is the JSON payload for budget.sync events sent from control server to edge gateways to synchronize budget usage.
type BudgetSyncService ¶
type BudgetSyncService struct {
// contains filtered or unexported fields
}
BudgetSyncService aggregates budget usage from llm_chat_records and publishes updates to edge gateways via the event bridge.
func NewBudgetSyncService ¶
func NewBudgetSyncService(db *gorm.DB, eventBus eventbridge.Bus) *BudgetSyncService
NewBudgetSyncService creates a new budget sync service. The interval can be configured via BUDGET_SYNC_INTERVAL environment variable.
func (*BudgetSyncService) GetSyncInterval ¶
func (s *BudgetSyncService) GetSyncInterval() time.Duration
GetSyncInterval returns the configured sync interval (for testing)
func (*BudgetSyncService) PeriodUsage ¶
PeriodUsage returns an App's spend in dollars for the budget period starting at periodStart, as of the latest sync cycle (at most one interval old). It reports false before the first cycle, for an App the cycle did not see, or when the App's period has changed since.
func (*BudgetSyncService) SetEdgeBudgetSource ¶
func (s *BudgetSyncService) SetEdgeBudgetSource(src EdgeBudgetSource)
SetEdgeBudgetSource makes every sync carry budget blocks and analyse Apps whose spend moved since the previous sync.
func (*BudgetSyncService) Start ¶
func (s *BudgetSyncService) Start()
Start begins the budget sync background task. It aggregates usage and publishes to edges at the configured interval.
func (*BudgetSyncService) Stop ¶
func (s *BudgetSyncService) Stop()
Stop gracefully stops the budget sync service.
type Config ¶
type Config struct {
GRPCPort int
GRPCHost string
TLSEnabled bool
TLSCertPath string
TLSKeyPath string
// TLSConfig, when set, is used for TLS instead of TLSCertPath and
// TLSKeyPath (and whatever TLSEnabled says): an embedding host supplies
// its own certificates, cipher suites and minimum version.
TLSConfig *tls.Config
AuthToken string
NextAuthToken string
MaxConcurrentStreams int // Maximum number of concurrent gRPC streams (default 1000)
// EncryptionKey is the 32-character key edges use to decrypt the
// credentials sent to them. Empty means MICROGATEWAY_ENCRYPTION_KEY.
EncryptionKey string
// NodeID identifies this Studio replica (pkg/cluster). It is recorded as
// the owner of every edge stream this server holds. Empty means
// "control", for a single replica.
NodeID string
// BudgetSyncInterval is how often budget usage is synced to edges.
// Zero means BUDGET_SYNC_INTERVAL, or 30s.
BudgetSyncInterval time.Duration
// MaxMessageSize bounds a message in either direction, in bytes (zero:
// 16 MB, the edge's own GRPC_MAX_MESSAGE_SIZE default). Configuration
// snapshots and analytics pulses outgrow gRPC's 4 MB default.
MaxMessageSize int
// KeepaliveMinTime is the shortest interval between client pings the
// server accepts, with or without an open stream (zero: 10s; edges ping
// every 30s). A client pinging more often is disconnected.
KeepaliveMinTime time.Duration
// MaxConnectionAge, when set, closes each connection after about this
// long, so edges spread again over replicas behind a load balancer;
// streams get MaxConnectionAgeGrace to finish. Zero keeps connections
// open: an edge's stream is long-lived, and pushes in flight on a closed
// stream go back to pending.
MaxConnectionAge time.Duration
MaxConnectionAgeGrace time.Duration
}
Config holds the control server configuration
type ControlServer ¶
type ControlServer struct {
pb.UnimplementedConfigurationSyncServiceServer
// contains filtered or unexported fields
}
ControlServer implements the ConfigurationSyncService for AI Studio control instances
func NewControlServer ¶
func NewControlServer(cfg *Config, db *gorm.DB) (*ControlServer, error)
NewControlServer creates a new control server for AI Studio. It fails when the microgateway encryption key is missing or insecure.
func (*ControlServer) GetEventBus ¶
func (s *ControlServer) GetEventBus() eventbridge.Bus
GetEventBus returns the control server's event bus for subscribing to events. This allows other AI Studio components to subscribe to events from edges.
func (*ControlServer) GetFullConfiguration ¶
func (s *ControlServer) GetFullConfiguration(ctx context.Context, req *pb.ConfigurationRequest) (*pb.ConfigurationSnapshot, error)
GetFullConfiguration retrieves a complete configuration snapshot for an edge. This is the path a reload uses (microgateway RequestFullSync). The namespace is resolved the way registration resolved it -- the registered edge's stored namespace when the edge is known, else the normalised request namespace -- so an edge whose EDGE_NAMESPACE is unset ("") pulls the same snapshot its heartbeat is compared against. The pulling edge is marked in sync at once, as the stream ConfigRequest path does, rather than waiting for a heartbeat.
func (*ControlServer) LocalStreams ¶
func (s *ControlServer) LocalStreams() map[string]string
LocalStreams lists the edges with a live stream on this replica that are ready for pushes (see pushReady), with the stream's session.
func (*ControlServer) RegisterEdge ¶
func (s *ControlServer) RegisterEdge(ctx context.Context, req *pb.EdgeRegistrationRequest) (*pb.EdgeRegistrationResponse, error)
RegisterEdge handles edge instance registration
func (*ControlServer) SendAnalyticsPulse ¶
func (s *ControlServer) SendAnalyticsPulse(ctx context.Context, req *pb.AnalyticsPulse) (*pb.AnalyticsPulseResponse, error)
SendAnalyticsPulse handles analytics pulse data from edge instances
func (*ControlServer) SendHeartbeat ¶
func (s *ControlServer) SendHeartbeat(ctx context.Context, req *pb.HeartbeatRequest) (*pb.HeartbeatResponse, error)
SendHeartbeat handles unary heartbeat requests, a deprecated RPC: edges heartbeat on their stream (SubscribeToChanges), which also tracks stream ownership. The unary call is answered from the database, so it works on any replica, not only the one holding the edge's stream; it records the heartbeat and leaves ownership alone.
func (*ControlServer) SendPluginControlBatch ¶
func (s *ControlServer) SendPluginControlBatch(ctx context.Context, req *pb.PluginControlBatch) (*pb.PluginControlBatchResponse, error)
SendPluginControlBatch handles plugin control payloads from edge instances This enables plugins running on edge (microgateway) to send data back to AI Studio control plane
func (*ControlServer) SendReload ¶
func (s *ControlServer) SendReload(edgeID, session string, req *pb.ConfigurationReloadRequest) error
SendReload sends a push on the edge's stream, provided it is still the stream with the given session: a push must go out on the stream it was claimed for, or not at all.
func (*ControlServer) Serve ¶
func (s *ControlServer) Serve(listener net.Listener) error
Serve serves the gRPC control server on listener until Stop is called. An embedding host uses it to supply its own listener.
func (*ControlServer) SetEdgeBudgetSource ¶
func (s *ControlServer) SetEdgeBudgetSource(src EdgeBudgetSource)
SetEdgeBudgetSource has the budget sync push budget blocks to edges and raise budget alerts for edge spend (Enterprise).
func (*ControlServer) SetEdgePayloadForwarder ¶
func (s *ControlServer) SetEdgePayloadForwarder(f EdgePayloadForwarder)
SetEdgePayloadForwarder has a replica without plugins (no SetPluginManager) forward edges' plugin payloads to one that has them. Set it before Serve.
func (*ControlServer) SetGovernedMetadataReader ¶
func (s *ControlServer) SetGovernedMetadataReader(reader governed_metadata.SnapshotReader)
SetGovernedMetadataReader wires the governed metadata service so gateway-visible fields are included in configuration snapshots. Safe to leave unset (CE).
func (*ControlServer) SetPluginManager ¶
func (s *ControlServer) SetPluginManager(manager interface{})
SetPluginManager sets the plugin manager reference for routing edge payloads
func (*ControlServer) SetPushDelivery ¶
func (s *ControlServer) SetPushDelivery(p PushDelivery)
SetPushDelivery connects the push coordinator. The coordinator in turn uses the server's LocalStreams and SendReload.
func (*ControlServer) Start ¶
func (s *ControlServer) Start() error
Start listens on the configured host and port and serves the gRPC control server until Stop is called.
func (*ControlServer) SubscribeToChanges ¶
func (s *ControlServer) SubscribeToChanges(stream pb.ConfigurationSyncService_SubscribeToChangesServer) error
SubscribeToChanges handles bidirectional streaming for real-time updates
func (*ControlServer) UnregisterEdge ¶
func (s *ControlServer) UnregisterEdge(ctx context.Context, req *pb.EdgeUnregistrationRequest) (*emptypb.Empty, error)
UnregisterEdge handles edge instance unregistration
func (*ControlServer) ValidateToken ¶
func (s *ControlServer) ValidateToken(ctx context.Context, req *pb.TokenValidationRequest) (*pb.TokenValidationResponse, error)
ValidateToken validates an API token on-demand with namespace filtering
type EdgeBudgetSource ¶
type EdgeBudgetSource interface {
EdgeBlocks() (map[uint]string, error)
AnalyzeApps(appIDs []uint)
}
EdgeBudgetSource is the Enterprise budget service as the budget sync sees it: the Apps edges must refuse, and threshold analysis for spend that reached Studio from edges (edge traffic never passes Studio's own budget check, so nothing else would raise its alerts).
type EdgeInstanceConnection ¶
type EdgeInstanceConnection struct {
EdgeID string
Namespace string
Status string
Version string
SessionID string
Stream pb.ConfigurationSyncService_SubscribeToChangesServer
LastHeartbeat time.Time
// contains filtered or unexported fields
}
EdgeInstance represents an active edge instance connection
type EdgePayloadForwarder ¶
type EdgePayloadForwarder interface {
ForwardEdgePayloads(ctx context.Context, payloads []*pb.PluginControlPayload) error
}
EdgePayloadForwarder takes an edge's plugin payloads to another replica that hosts the plugins, for a replica without them (a headless control plane): a whole batch at once, all or none. A nil error means they are queued for that replica, not that a plugin has handled them.
type EdgePayloadRouter ¶
type EdgePayloadRouter interface {
RouteEdgePayload(ctx context.Context, payload *pb.PluginControlPayload) error
}
EdgePayloadRouter interface for routing edge payloads to plugins
type PushDelivery ¶
type PushDelivery interface {
StreamOpened(edgeID string)
StreamClosed(edgeID, session string)
HandleReloadResponse(*pb.ConfigurationReloadResponse)
}
PushDelivery is the durable push coordinator (services/pushes.Coordinator), told about this replica's edge streams and the edges' reload reports.