Files
telecom-platform/apps/carrier-connector/internal/handlers/smdp_handler.go
T
NutcaseandGitHub d61aa93bd5 Multi carriersm dp+ (#61)
* refactor: Rename handler package to handlers in carrier-connector

- Rename internal/handler directory to internal/handlers
- Update handler import path in main.go and routes.go

* feat: Add SM-DP+ handler with multi-carrier management and profile operations

- Add SMDPHandler struct with manager field and NewSMDPHandler constructor
- Add AddCarrier endpoint with JSON binding and carrier configuration support
- Add RemoveCarrier endpoint with carrier ID parameter validation
- Add DownloadProfile endpoint with 30-second timeout and context cancellation
- Add GetCarrierStatus endpoint returning all carriers with timestamp
- Add GetProfileStatus endpoint with EID/ICCID validation

* feat: Add SM-DP+ integration layer with multi-carrier system initialization and route registration

- Add SMDPIntegration struct with service, handler, repository, and logger fields
- Add NewSMDPIntegration constructor with default carrier initialization
- Add InitializeSystem method with carrier health logging and status tracking
- Add RegisterRoutes method with profile, carrier, health, and metrics endpoints
- Add healthHandler with carrier health status aggregation and degraded state detection
- Add metricsHandler

* feat: Add SM-DP+ service layer with multi-carrier management and profile download operations

- Add SMDPService struct with manager, repository, and logger fields
- Add NewSMDPService constructor with default config and background health checking
- Add InitializeDefaultCarriers with AT&T, Verizon, and T-Mobile DE configurations
- Add DownloadProfile method with context support and request logging
- Add GetOptimalCarrier wrapping SelectCarrier for best carrier selection
- Add GetCarrierHealth returning

* feat: Add SM-DP+ manager with multi-carrier load balancing, health checking, and profile operations

- Add DefaultManagerConfig with 30s health checks, 3 retries, and circuit breaker configuration
- Add CarrierConfig struct with ES2 settings, MCC/MNC, priority, and feature support
- Add ToCarrier method converting CarrierConfig to Carrier with metrics and capabilities
- Add HealthChecker with periodic carrier health monitoring and status evaluation
- Add LoadBalancer with weighted round-robin, least
2026-05-01 20:24:34 +03:00

135 lines
3.5 KiB
Go

package handlers
import (
"context"
"net/http"
"time"
"github.com/gin-gonic/gin"
"github.com/nutcas3/telecom-platform/apps/carrier-connector/internal/repository"
"github.com/nutcas3/telecom-platform/apps/carrier-connector/internal/smdp"
)
// SMDPHandler handles SM-DP+ multi-carrier operations
type SMDPHandler struct {
manager *smdp.SMDPManager
}
// NewSMDPHandler creates a new SM-DP+ handler
func NewSMDPHandler(repo *repository.PostgresProfileStore) *SMDPHandler {
config := smdp.DefaultManagerConfig()
manager := smdp.NewSMDPManager(repo, config)
// Start health checking in background
ctx := context.Background()
go manager.StartHealthChecking(ctx)
return &SMDPHandler{
manager: manager,
}
}
// AddCarrier adds a new carrier to the SM-DP+ manager
func (h *SMDPHandler) AddCarrier(c *gin.Context) {
var carrierConfig smdp.CarrierConfig
if err := c.ShouldBindJSON(&carrierConfig); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
carrier := carrierConfig.ToCarrier()
if err := h.manager.AddCarrier(carrier); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusCreated, gin.H{
"message": "Carrier added successfully",
"carrier_id": carrier.ID,
})
}
// RemoveCarrier removes a carrier from the SM-DP+ manager
func (h *SMDPHandler) RemoveCarrier(c *gin.Context) {
carrierID := c.Param("id")
if carrierID == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "Carrier ID is required"})
return
}
if err := h.manager.RemoveCarrier(carrierID); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"message": "Carrier removed successfully"})
}
// DownloadProfile handles eSIM profile download with multi-carrier support
func (h *SMDPHandler) DownloadProfile(c *gin.Context) {
var req smdp.ProfileRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
ctx, cancel := context.WithTimeout(c.Request.Context(), 30*time.Second)
defer cancel()
response, err := h.manager.DownloadProfile(ctx, &req)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{
"error": err.Error(),
"response": response,
})
return
}
c.JSON(http.StatusOK, response)
}
// GetCarrierStatus returns the status of all carriers
func (h *SMDPHandler) GetCarrierStatus(c *gin.Context) {
status := h.manager.GetCarrierStatus()
c.JSON(http.StatusOK, gin.H{
"carriers": status,
"timestamp": time.Now(),
})
}
// GetProfileStatus gets profile status from the best available carrier
func (h *SMDPHandler) GetProfileStatus(c *gin.Context) {
var req struct {
EID string `json:"eid" binding:"required"`
ICCID string `json:"iccid" binding:"required"`
}
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
// Create profile request for status check
profileReq := &smdp.ProfileRequest{
EID: req.EID,
ICCID: req.ICCID,
}
ctx, cancel := context.WithTimeout(c.Request.Context(), 30*time.Second)
defer cancel()
// Use the manager to select best carrier and get status
carrier, err := h.manager.SelectCarrier(ctx, profileReq)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{
"carrier_id": carrier.ID,
"carrier_name": carrier.Name,
"health_status": carrier.HealthStatus,
"message": "Use specific carrier endpoint for detailed status",
})
}