From 9914ee59559873bcc519a6de4fd534e9249e766a Mon Sep 17 00:00:00 2001 From: nutcas3 Date: Sun, 3 May 2026 10:51:11 +0300 Subject: [PATCH] feat: Add geographic routing service with region management, IP-based routing, and endpoint selection - Add GeoRouter struct with regions map, defaultReg, and mutex fields - Add Region struct with ID, Name, Endpoints, Priority, IsActive, and Latency fields - Add GeoRoutingConfig with DefaultRegion and Regions fields - Add NewGeoRouter constructor with region initialization - Add GetRegionForIP method with IP parsing and geo lookup - Add lookupRegion helper with simplified IP range-based region detection --- .../internal/infra/georouting.go | 112 ++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 apps/carrier-connector/internal/infra/georouting.go diff --git a/apps/carrier-connector/internal/infra/georouting.go b/apps/carrier-connector/internal/infra/georouting.go new file mode 100644 index 0000000..1e467fe --- /dev/null +++ b/apps/carrier-connector/internal/infra/georouting.go @@ -0,0 +1,112 @@ +package infra + +import ( + "context" + "net" + "sync" +) + +// GeoRouter handles geographic routing for API requests +type GeoRouter struct { + regions map[string]*Region + defaultReg string + mu sync.RWMutex +} + +// Region represents a geographic region with endpoints +type Region struct { + ID string `json:"id"` + Name string `json:"name"` + Endpoints []string `json:"endpoints"` + Priority int `json:"priority"` + IsActive bool `json:"is_active"` + Latency float64 `json:"latency_ms"` +} + +// GeoRoutingConfig configures geographic routing +type GeoRoutingConfig struct { + DefaultRegion string + Regions []*Region +} + +// NewGeoRouter creates a new geographic router +func NewGeoRouter(config GeoRoutingConfig) *GeoRouter { + gr := &GeoRouter{ + regions: make(map[string]*Region), + defaultReg: config.DefaultRegion, + } + for _, r := range config.Regions { + gr.regions[r.ID] = r + } + return gr +} + +// GetRegionForIP determines the best region for an IP address +func (gr *GeoRouter) GetRegionForIP(_ context.Context, ipStr string) (*Region, error) { + gr.mu.RLock() + defer gr.mu.RUnlock() + + ip := net.ParseIP(ipStr) + if ip == nil { + return gr.regions[gr.defaultReg], nil + } + + // Simplified geo lookup - in production use MaxMind GeoIP + regionID := gr.lookupRegion(ip) + if region, ok := gr.regions[regionID]; ok && region.IsActive { + return region, nil + } + + return gr.regions[gr.defaultReg], nil +} + +func (gr *GeoRouter) lookupRegion(ip net.IP) string { + // Simplified region detection based on IP ranges + if ip.To4() != nil { + first := ip.To4()[0] + switch { + case first >= 1 && first <= 126: + return "us-east" + case first >= 128 && first <= 191: + return "eu-west" + default: + return "ap-southeast" + } + } + return gr.defaultReg +} + +// GetBestEndpoint returns the best endpoint for a region +func (gr *GeoRouter) GetBestEndpoint(_ context.Context, regionID string) (string, error) { + gr.mu.RLock() + defer gr.mu.RUnlock() + + region, ok := gr.regions[regionID] + if !ok || len(region.Endpoints) == 0 { + region = gr.regions[gr.defaultReg] + } + + if len(region.Endpoints) > 0 { + return region.Endpoints[0], nil + } + return "", nil +} + +// UpdateRegion updates a region configuration +func (gr *GeoRouter) UpdateRegion(region *Region) { + gr.mu.Lock() + defer gr.mu.Unlock() + gr.regions[region.ID] = region +} + +// GetRegions returns all configured regions +func (gr *GeoRouter) GetRegions() []*Region { + gr.mu.RLock() + defer gr.mu.RUnlock() + + regions := make([]*Region, 0, len(gr.regions)) + for _, r := range gr.regions { + regions = append(regions, r) + } + return regions +}