mirror of
https://github.com/andwati/telecom-platform.git
synced 2026-10-22 04:34:27 +00:00
feat: Add carrier selection integration layer with multi-carrier setup, HTTP server, and demo capabilities
- Add SelectionIntegration struct with manager, selection service, handler, and SMDP service fields - Add NewSelectionIntegration constructor with default manager config and 30s health checks - Add SetupCarriers with AT&T, Verizon, T-Mobile DE, and Orange FR configurations - Add StartServer method with health endpoint and 30s read/write timeouts - Add StartHealthChecking wrapper for background
This commit is contained in:
@@ -0,0 +1,327 @@
|
||||
package integration
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/nutcas3/telecom-platform/apps/carrier-connector/internal/config"
|
||||
"github.com/nutcas3/telecom-platform/apps/carrier-connector/internal/handlers"
|
||||
"github.com/nutcas3/telecom-platform/apps/carrier-connector/internal/repository"
|
||||
"github.com/nutcas3/telecom-platform/apps/carrier-connector/internal/service"
|
||||
"github.com/nutcas3/telecom-platform/apps/carrier-connector/internal/smdp"
|
||||
)
|
||||
|
||||
// SelectionIntegration wires together the carrier selection components
|
||||
type SelectionIntegration struct {
|
||||
manager *smdp.SMDPManager
|
||||
selectionService *service.SelectionService
|
||||
selectionHandler *handlers.SelectionHandler
|
||||
smdpService *service.SMDPService
|
||||
server *http.Server
|
||||
}
|
||||
|
||||
// NewSelectionIntegration creates a new selection integration
|
||||
func NewSelectionIntegration(repo *repository.PostgresProfileStore) *SelectionIntegration {
|
||||
// Create SMDP manager with default configuration
|
||||
config := &smdp.ManagerConfig{
|
||||
HealthCheckInterval: 30 * time.Second,
|
||||
EnableFailover: true,
|
||||
EnableLoadBalancing: true,
|
||||
MaxRetries: 3,
|
||||
RetryDelay: 1 * time.Second,
|
||||
}
|
||||
|
||||
manager := smdp.NewSMDPManager(repo, config)
|
||||
|
||||
// Create selection service
|
||||
selectionService := service.NewSelectionService(manager)
|
||||
|
||||
// Create SMDP service
|
||||
smdpService := service.NewSMDPService(repo)
|
||||
|
||||
return &SelectionIntegration{
|
||||
manager: manager,
|
||||
selectionService: selectionService,
|
||||
selectionHandler: selectionService.GetHandler(),
|
||||
smdpService: smdpService,
|
||||
}
|
||||
}
|
||||
|
||||
// SetupCarriers configures default carriers for demonstration
|
||||
func (si *SelectionIntegration) SetupCarriers() error {
|
||||
// Configure sample carriers with different characteristics
|
||||
carriers := []*smdp.Carrier{
|
||||
{
|
||||
ID: "att-us",
|
||||
Name: "AT&T US",
|
||||
MCC: "310",
|
||||
MNC: "410",
|
||||
CountryCode: "US",
|
||||
IsActive: true,
|
||||
Priority: 90,
|
||||
ES2Config: &config.ES2Config{
|
||||
BaseURL: "https://es2plus.att.com",
|
||||
APIKey: "demo-key-att",
|
||||
InsecureSkipVerify: false,
|
||||
FunctionalityRequesterID: "telecom-platform",
|
||||
},
|
||||
Capabilities: &smdp.CarrierCapabilities{
|
||||
SupportedProfileTypes: []string{"operational", "testing"},
|
||||
Features: []string{"bulk_download", "remote_provisioning"},
|
||||
MaxConcurrentRequests: 100,
|
||||
},
|
||||
Metrics: &smdp.CarrierMetrics{
|
||||
TotalRequests: 1000,
|
||||
SuccessfulRequests: 980,
|
||||
FailedRequests: 20,
|
||||
AverageResponseTime: 150 * time.Millisecond,
|
||||
RequestRate: 10.5,
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "verizon-us",
|
||||
Name: "Verizon US",
|
||||
MCC: "311",
|
||||
MNC: "480",
|
||||
CountryCode: "US",
|
||||
IsActive: true,
|
||||
Priority: 85,
|
||||
ES2Config: &config.ES2Config{
|
||||
BaseURL: "https://es2plus.verizon.com",
|
||||
APIKey: "demo-key-verizon",
|
||||
InsecureSkipVerify: false,
|
||||
FunctionalityRequesterID: "telecom-platform",
|
||||
},
|
||||
Capabilities: &smdp.CarrierCapabilities{
|
||||
SupportedProfileTypes: []string{"operational", "testing"},
|
||||
Features: []string{"bulk_download"},
|
||||
MaxConcurrentRequests: 80,
|
||||
},
|
||||
Metrics: &smdp.CarrierMetrics{
|
||||
TotalRequests: 800,
|
||||
SuccessfulRequests: 790,
|
||||
FailedRequests: 10,
|
||||
AverageResponseTime: 120 * time.Millisecond,
|
||||
RequestRate: 8.2,
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "tmobile-de",
|
||||
Name: "T-Mobile Germany",
|
||||
MCC: "262",
|
||||
MNC: "01",
|
||||
CountryCode: "DE",
|
||||
IsActive: true,
|
||||
Priority: 75,
|
||||
ES2Config: &config.ES2Config{
|
||||
BaseURL: "https://es2plus.t-mobile.de",
|
||||
APIKey: "demo-key-tmobile",
|
||||
InsecureSkipVerify: false,
|
||||
FunctionalityRequesterID: "telecom-platform",
|
||||
},
|
||||
Capabilities: &smdp.CarrierCapabilities{
|
||||
SupportedProfileTypes: []string{"operational"},
|
||||
Features: []string{"remote_provisioning"},
|
||||
MaxConcurrentRequests: 60,
|
||||
},
|
||||
Metrics: &smdp.CarrierMetrics{
|
||||
TotalRequests: 600,
|
||||
SuccessfulRequests: 570,
|
||||
FailedRequests: 30,
|
||||
AverageResponseTime: 200 * time.Millisecond,
|
||||
RequestRate: 6.8,
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "orange-fr",
|
||||
Name: "Orange France",
|
||||
MCC: "208",
|
||||
MNC: "01",
|
||||
CountryCode: "FR",
|
||||
IsActive: true,
|
||||
Priority: 70,
|
||||
ES2Config: &config.ES2Config{
|
||||
BaseURL: "https://es2plus.orange.fr",
|
||||
APIKey: "demo-key-orange",
|
||||
InsecureSkipVerify: false,
|
||||
FunctionalityRequesterID: "telecom-platform",
|
||||
},
|
||||
Capabilities: &smdp.CarrierCapabilities{
|
||||
SupportedProfileTypes: []string{"operational", "testing"},
|
||||
Features: []string{},
|
||||
MaxConcurrentRequests: 50,
|
||||
},
|
||||
Metrics: &smdp.CarrierMetrics{
|
||||
TotalRequests: 400,
|
||||
SuccessfulRequests: 380,
|
||||
FailedRequests: 20,
|
||||
AverageResponseTime: 180 * time.Millisecond,
|
||||
RequestRate: 4.5,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// Add carriers to the manager
|
||||
for _, carrier := range carriers {
|
||||
if err := si.manager.AddCarrier(carrier); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
log.Printf("Added %d carriers to the selection manager", len(carriers))
|
||||
return nil
|
||||
}
|
||||
|
||||
// StartServer starts the HTTP server with all endpoints
|
||||
func (si *SelectionIntegration) StartServer(port string) error {
|
||||
// Create HTTP multiplexer
|
||||
mux := http.NewServeMux()
|
||||
|
||||
// Register selection routes
|
||||
si.selectionHandler.RegisterRoutes(mux)
|
||||
|
||||
// Add health check endpoint
|
||||
mux.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte(`{"status": "healthy", "service": "selection-integration"}`))
|
||||
})
|
||||
|
||||
// Create and configure server
|
||||
si.server = &http.Server{
|
||||
Addr: ":" + port,
|
||||
Handler: mux,
|
||||
ReadTimeout: 30 * time.Second,
|
||||
WriteTimeout: 30 * time.Second,
|
||||
IdleTimeout: 120 * time.Second,
|
||||
}
|
||||
|
||||
log.Printf("Starting selection integration server on port %s", port)
|
||||
return si.server.ListenAndServe()
|
||||
}
|
||||
|
||||
// StartHealthChecking starts the background health checking process
|
||||
func (si *SelectionIntegration) StartHealthChecking(ctx context.Context) {
|
||||
si.manager.StartHealthChecking(ctx)
|
||||
}
|
||||
|
||||
// GetManager returns the SMDP manager for testing
|
||||
func (si *SelectionIntegration) GetManager() *smdp.SMDPManager {
|
||||
return si.manager
|
||||
}
|
||||
|
||||
// GetSelectionService returns the selection service for testing
|
||||
func (si *SelectionIntegration) GetSelectionService() *service.SelectionService {
|
||||
return si.selectionService
|
||||
}
|
||||
|
||||
// Shutdown gracefully shuts down the server
|
||||
func (si *SelectionIntegration) Shutdown(ctx context.Context) error {
|
||||
if si.server != nil {
|
||||
return si.server.Shutdown(ctx)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RunDemo runs a demonstration of the carrier selection capabilities
|
||||
func (si *SelectionIntegration) RunDemo(ctx context.Context) error {
|
||||
log.Println("Starting carrier selection demonstration...")
|
||||
|
||||
// Setup carriers
|
||||
if err := si.SetupCarriers(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Start health checking
|
||||
si.StartHealthChecking(ctx)
|
||||
|
||||
// Wait a moment for health checks to initialize
|
||||
time.Sleep(2 * time.Second)
|
||||
|
||||
// Demonstrate intelligent carrier selection
|
||||
log.Println("Demonstrating intelligent carrier selection...")
|
||||
|
||||
// Test different selection scenarios
|
||||
scenarios := []struct {
|
||||
name string
|
||||
criteria *smdp.SelectionCriteria
|
||||
}{
|
||||
{
|
||||
name: "High Priority US Request",
|
||||
criteria: &smdp.SelectionCriteria{
|
||||
Region: "US",
|
||||
ProfileType: "operational",
|
||||
Urgency: "high",
|
||||
CostSensitivity: 0.2,
|
||||
PerformanceWeight: 0.6,
|
||||
ReliabilityWeight: 0.6,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Cost-Optimized European Request",
|
||||
criteria: &smdp.SelectionCriteria{
|
||||
Region: "DE",
|
||||
ProfileType: "operational",
|
||||
Urgency: "low",
|
||||
CostSensitivity: 0.8,
|
||||
PerformanceWeight: 0.2,
|
||||
ReliabilityWeight: 0.3,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Balanced Global Request",
|
||||
criteria: &smdp.SelectionCriteria{
|
||||
Region: "",
|
||||
ProfileType: "operational",
|
||||
Urgency: "medium",
|
||||
CostSensitivity: 0.5,
|
||||
PerformanceWeight: 0.4,
|
||||
ReliabilityWeight: 0.4,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, scenario := range scenarios {
|
||||
log.Printf("Testing scenario: %s", scenario.name)
|
||||
|
||||
score, err := si.manager.SelectOptimalCarrier(ctx, scenario.criteria)
|
||||
if err != nil {
|
||||
log.Printf("Error in scenario %s: %v", scenario.name, err)
|
||||
continue
|
||||
}
|
||||
|
||||
log.Printf("Selected carrier: %s (%s)", score.Carrier.Name, score.CarrierID)
|
||||
log.Printf("Total score: %.2f", score.TotalScore)
|
||||
log.Printf("Performance: %.2f, Reliability: %.2f, Cost: %.2f, Region: %.2f, Capability: %.2f",
|
||||
score.PerformanceScore, score.ReliabilityScore, score.CostScore, score.RegionScore, score.CapabilityScore)
|
||||
log.Printf("Reason: %s", score.Reason)
|
||||
log.Println("---")
|
||||
}
|
||||
|
||||
// Demonstrate analytics
|
||||
log.Println("Generating carrier analytics...")
|
||||
analytics, err := si.selectionService.GetCarrierAnalytics(ctx)
|
||||
if err != nil {
|
||||
log.Printf("Error generating analytics: %v", err)
|
||||
} else {
|
||||
log.Printf("Analytics generated for %d carriers", analytics.TotalCarriers)
|
||||
log.Printf("Overall health: %.1f%%", analytics.Summary.OverallHealth)
|
||||
log.Printf("Overall success rate: %.1f%%", analytics.Summary.OverallSuccessRate)
|
||||
}
|
||||
|
||||
// Demonstrate optimization recommendations
|
||||
log.Println("Generating optimization recommendations...")
|
||||
optimization, err := si.selectionService.OptimizeCarrierSelection(ctx)
|
||||
if err != nil {
|
||||
log.Printf("Error generating optimization: %v", err)
|
||||
} else {
|
||||
log.Printf("System health: %.1f%%", optimization.OverallHealth)
|
||||
log.Printf("Recommendations: %d", len(optimization.Recommendations))
|
||||
log.Printf("Priority actions: %d", len(optimization.PriorityActions))
|
||||
}
|
||||
|
||||
log.Println("Carrier selection demonstration completed successfully!")
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user