5.8 KiB
Configuration Query
Read-only access to the active configuration state, including route providers and system statistics.
Overview
The internal/config/query package offers read-only access to the active configuration state. It provides functions to dump route providers, list providers, search for routes, and retrieve system statistics. This package is primarily used by the API layer to expose configuration information.
Primary consumers
internal/api/v1- REST API endpoints for configuration queriesinternal/homepage- Dashboard statistics display- Operators - CLI tools and debugging interfaces
Non-goals
- Configuration modification (see
internal/config) - Provider lifecycle management
- Dynamic state updates
Stability
Stable internal package. Functions are simple read-only accessors.
Public API
Exported types
type RouteProviderListResponse struct {
ShortName string `json:"short_name"`
FullName string `json:"full_name"`
}
type Statistics struct {
Total uint16 `json:"total"`
ReverseProxies types.RouteStats `json:"reverse_proxies"`
Streams types.RouteStats `json:"streams"`
Providers map[string]types.ProviderStats `json:"providers"`
}
Exported functions
func DumpRouteProviders() map[string]types.RouteProvider
Returns all route providers as a map keyed by their short name. Thread-safe access via config.ActiveState.Load().
func RouteProviderList() []RouteProviderListResponse
Returns a list of route providers with their short and full names. Useful for API responses.
func SearchRoute(alias string) types.Route
Searches for a route by alias across all providers. Returns nil if not found.
func GetStatistics() Statistics
Aggregates statistics from all route providers, including total routes, reverse proxies, streams, and per-provider stats.
Architecture
Core components
config/query/
├── query.go # Provider and route queries
└── stats.go # Statistics aggregation
Data flow
graph TD
A[API Request] --> B[config/query Functions]
B --> C{Query Type}
C -->|Provider List| D[ActiveState.Load]
C -->|Route Search| E[Iterate Providers]
C -->|Statistics| F[Aggregate from All Providers]
D --> G[Return Provider Data]
E --> H[Return Found Route or nil]
F --> I[Return Statistics]
Thread safety model
All functions use config.ActiveState.Load() for thread-safe read access:
func DumpRouteProviders() map[string]types.RouteProvider {
state := config.ActiveState.Load()
entries := make(map[string]types.RouteProvider, state.NumProviders())
for _, p := range state.IterProviders() {
entries[p.ShortName()] = p
}
return entries
}
Configuration Surface
No configuration. This package only reads from the active state.
Dependency and Integration Map
Internal dependencies
internal/config/types-ActiveStateatomic pointer andStateinterfaceinternal/types- Route provider and route types
Integration points
// API endpoint uses query functions
func ListProviders(w http.ResponseWriter, r *http.Request) {
providers := statequery.RouteProviderList()
json.NewEncoder(w).Encode(providers)
}
Observability
Logs
No logging in the query package itself.
Metrics
No metrics are currently exposed.
Security Considerations
- Read-only access prevents state corruption
- No sensitive data is exposed beyond what the configuration already contains
- Caller should handle nil state gracefully
Failure Modes and Recovery
| Failure | Behavior | Recovery |
|---|---|---|
| No active state | Functions return empty/nil | Initialize config first |
| Provider returns nil | Skipped in iteration | Provider should not return nil |
| Route not found | Returns nil | Expected behavior |
Performance Characteristics
- O(n) where n is number of providers for provider queries
- O(n * m) where m is routes per provider for route search
- O(n) for statistics aggregation
- No locking required (uses atomic load)
Usage Examples
Listing all providers
providers := statequery.RouteProviderList()
for _, p := range providers {
fmt.Printf("Short: %s, Full: %s\n", p.ShortName, p.FullName)
}
Getting all providers as a map
providers := statequery.DumpRouteProviders()
for shortName, provider := range providers {
fmt.Printf("%s: %s\n", shortName, provider.String())
}
Searching for a route
route := statequery.SearchRoute("my-service")
if route != nil {
fmt.Printf("Found route: %s\n", route.Alias())
}
Getting system statistics
stats := statequery.GetStatistics()
fmt.Printf("Total routes: %d\n", stats.Total)
fmt.Printf("Reverse proxies: %d\n", stats.ReverseProxies.Total)
for name, providerStats := range stats.Providers {
fmt.Printf("Provider %s: %d routes\n", name, providerStats.RPs.Total)
}
Integration with API
func handleGetProviders(w http.ResponseWriter, r *http.Request) {
providers := statequery.RouteProviderList()
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(providers)
}
func handleGetStats(w http.ResponseWriter, r *http.Request) {
stats := statequery.GetStatistics()
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(stats)
}
func handleFindRoute(w http.ResponseWriter, r *http.Request) {
alias := r.URL.Query().Get("alias")
route := statequery.SearchRoute(alias)
if route == nil {
http.NotFound(w, r)
return
}
json.NewEncoder(w).Encode(route)
}