Skip to content

Commit

Permalink
refactor code for circuit breaker configs
Browse files Browse the repository at this point in the history
  • Loading branch information
Thushani-Jayasekera committed Sep 9, 2024
1 parent 369f1a1 commit 206a1eb
Show file tree
Hide file tree
Showing 6 changed files with 127 additions and 62 deletions.
29 changes: 17 additions & 12 deletions adapter/config/default_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ var defaultConfig = &Config{
SandboxVhost: "sandbox.host",
SandboxEnvName: "sandbox",
IsIntelligentRoutingEnabled: false,
PaidOrganizations: "e0682456-2ba6-4c5f-8f36-3c5b6dc46913,4b9afefb-4bcc-4e63-85d3-ddd593841012,d3a7dfea-fb10-4371-b21d-85d1bc28667b",
},
Envoy: envoy{
ListenerHost: "0.0.0.0",
Expand Down Expand Up @@ -140,17 +139,23 @@ var defaultConfig = &Config{
},
},
},
BasicCircuitBreaker: upstreamCircuitBreaker{
MaxConnections: 3,
MaxRequests: 3,
MaxPendingRequests: 1,
MaxRetries: 3,
},
EnhancedCircuitBreaker: upstreamCircuitBreaker{
MaxConnections: 50,
MaxRequests: 50,
MaxPendingRequests: 1,
MaxRetries: 3,
CircuitBreakers: []upstreamCircuitBreaker{
{
Organizations: "*",
CircuitBreakerName: "BasicCircuitBreaker",
MaxConnections: 3,
MaxRequests: 3,
MaxPendingRequests: 1,
MaxRetries: 3,
},
{
Organizations: "e0682456-2ba6-4c5f-8f36-3c5b6dc46913,4b9afefb-4bcc-4e63-85d3-ddd593841012,d3a7dfea-fb10-4371-b21d-85d1bc28667b",
CircuitBreakerName: "EnhancedCircuitBreaker",
MaxConnections: 50,
MaxRequests: 50,
MaxPendingRequests: 1,
MaxRetries: 50,
},
},
},
Connection: connection{
Expand Down
25 changes: 2 additions & 23 deletions adapter/config/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,8 @@ const (

// Constants related to utility functions
const (
tenantDomainSeparator = "@"
superTenantDomain = "carbon.super"
organizationListSeparator = ","
tenantDomainSeparator = "@"
superTenantDomain = "carbon.super"
)

// ReadConfigs implements adapter configuration read operation. The read operation will happen only once, hence
Expand Down Expand Up @@ -182,26 +181,6 @@ func GetControlPlaneConnectedTenantDomain() string {
return superTenantDomain
}

// GetIsPaidOrganization returns whether the organization is a paid organization or not.
func GetIsPaidOrganization(orgID string) bool {
conf, _ := ReadConfigs()

// Populate data from the config
paidOrganizations := conf.Adapter.PaidOrganizations
paidOrganizationsList := strings.Split(paidOrganizations, organizationListSeparator)

// Convert the list to a set for O(1) lookup
paidOrganizationsSet := make(map[string]struct{}, len(paidOrganizationsList))
for _, org := range paidOrganizationsList {
paidOrganizationsSet[org] = struct{}{}
}

// Check if the orgID is in the set
_, exists := paidOrganizationsSet[orgID]
return exists

}

func (config *Config) resolveDeprecatedProperties() {
if config.ControlPlane.ServiceURLDeprecated != UnassignedAsDeprecated {
printDeprecatedWarningLog("controlPlane.serviceUrl", "controlPlane.serviceURL")
Expand Down
17 changes: 8 additions & 9 deletions adapter/config/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,6 @@ type adapter struct {
SandboxEnvName string
// Feature flag to enable semantic version based intelligent routing
IsIntelligentRoutingEnabled bool
// PaidOrganizations contains the list of paid organizations
PaidOrganizations string
}

// Envoy Listener Component related configurations.
Expand Down Expand Up @@ -237,13 +235,12 @@ type globalCors struct {
// Envoy Upstream Related Configurations
type envoyUpstream struct {
// UpstreamTLS related Configuration
TLS upstreamTLS
Timeouts upstreamTimeout
Health upstreamHealth
DNS upstreamDNS
Retry upstreamRetry
EnhancedCircuitBreaker upstreamCircuitBreaker
BasicCircuitBreaker upstreamCircuitBreaker
TLS upstreamTLS
Timeouts upstreamTimeout
Health upstreamHealth
DNS upstreamDNS
Retry upstreamRetry
CircuitBreakers []upstreamCircuitBreaker
}

type upstreamTLS struct {
Expand Down Expand Up @@ -319,6 +316,8 @@ type upstreamRetry struct {
}

type upstreamCircuitBreaker struct {
Organizations string
CircuitBreakerName string
MaxConnections uint32
MaxPendingRequests uint32
MaxRequests uint32
Expand Down
61 changes: 43 additions & 18 deletions adapter/internal/oasparser/model/mgw_swagger.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,9 @@ type InterceptEndpoint struct {

const prototypedAPI = "prototyped"

// CircuitBreaker names for free tier
const BasicCircuitBreaker = "BasicCircuitBreaker"

// GetCorsConfig returns the CorsConfiguration Object.
func (swagger *MgwSwagger) GetCorsConfig() *CorsConfig {
return swagger.xWso2Cors
Expand Down Expand Up @@ -670,31 +673,53 @@ func (endpointCluster *EndpointCluster) SetEndpointsConfig(endpointInfos []Endpo
if endpointCluster.Config.CircuitBreakers == nil && apiType == "WS" {
logger.LoggerOasparser.Debug("Adding CircuitBreakers for the endpoint cluster", endpointInfos[0].Endpoint)
conf, _ := config.ReadConfigs()
isPaidOrg := config.GetIsPaidOrganization(orgID)
if isPaidOrg {
CircuitBreaker := &CircuitBreakers{
MaxConnections: int32(conf.Envoy.Upstream.EnhancedCircuitBreaker.MaxConnections),
MaxConnectionPools: int32(conf.Envoy.Upstream.EnhancedCircuitBreaker.MaxConnectionPools),
MaxPendingRequests: int32(conf.Envoy.Upstream.EnhancedCircuitBreaker.MaxPendingRequests),
MaxRequests: int32(conf.Envoy.Upstream.EnhancedCircuitBreaker.MaxRequests),
MaxRetries: int32(conf.Envoy.Upstream.EnhancedCircuitBreaker.MaxRetries),
var selectedCircuitBreaker *CircuitBreakers

for _, circuitBreaker := range conf.Envoy.Upstream.CircuitBreakers {
if utills.GetIsOrganizationInList(orgID, circuitBreaker.Organizations) {
selectedCircuitBreaker = createCircuitBreaker(
circuitBreaker.MaxConnections,
circuitBreaker.MaxPendingRequests,
circuitBreaker.MaxRequests,
circuitBreaker.MaxRetries,
circuitBreaker.MaxConnectionPools,
)
break
}
endpointCluster.Config.CircuitBreakers = CircuitBreaker
} else {
CircuitBreaker := &CircuitBreakers{
MaxConnections: int32(conf.Envoy.Upstream.BasicCircuitBreaker.MaxConnections),
MaxConnectionPools: int32(conf.Envoy.Upstream.BasicCircuitBreaker.MaxConnectionPools),
MaxPendingRequests: int32(conf.Envoy.Upstream.BasicCircuitBreaker.MaxPendingRequests),
MaxRequests: int32(conf.Envoy.Upstream.BasicCircuitBreaker.MaxRequests),
MaxRetries: int32(conf.Envoy.Upstream.BasicCircuitBreaker.MaxRetries),
}
if selectedCircuitBreaker == nil {
for _, circuitBreaker := range conf.Envoy.Upstream.CircuitBreakers {
// breaks from the first iteration
if circuitBreaker.CircuitBreakerName == BasicCircuitBreaker {
selectedCircuitBreaker = createCircuitBreaker(
circuitBreaker.MaxConnections,
circuitBreaker.MaxPendingRequests,
circuitBreaker.MaxRequests,
circuitBreaker.MaxRetries,
circuitBreaker.MaxConnectionPools,
)
break
}

}
endpointCluster.Config.CircuitBreakers = CircuitBreaker
}
endpointCluster.Config.CircuitBreakers = selectedCircuitBreaker
}

return nil
}

// Helper function to create a CircuitBreakers instance
func createCircuitBreaker(maxConnections uint32, maxPendingRequests uint32,
maxRequests uint32, maxRetries uint32, maxConnectionPools uint32) *CircuitBreakers {
return &CircuitBreakers{
MaxConnections: int32(maxConnections),
MaxConnectionPools: int32(maxConnectionPools),
MaxPendingRequests: int32(maxPendingRequests),
MaxRequests: int32(maxRequests),
MaxRetries: int32(maxRetries),
}
}

func (swagger *MgwSwagger) setXWso2ThrottlingTier() {
tier := ResolveThrottlingTier(swagger.vendorExtensions)
if tier != "" {
Expand Down
39 changes: 39 additions & 0 deletions adapter/internal/oasparser/utills/mgw_swagger_utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

// Package utills holds the implementation for common utility functions
package utills

import (
"strings"
)

// GetIsOrganizationInList returns whether the organization is in the list of organizations that has the circuit breaker.
func GetIsOrganizationInList(orgID string, cbOrganizationList string) bool {

cbOrganizationsList := strings.Split(cbOrganizationList, ",")

// Convert the list to a set for O(1) lookup
cbOrganizationsSet := make(map[string]struct{}, len(cbOrganizationsList))
for _, org := range cbOrganizationsList {
cbOrganizationsSet[org] = struct{}{}
}

// Check if the orgID is in the set
_, exists := cbOrganizationsSet[orgID]
return exists
}
18 changes: 18 additions & 0 deletions resources/conf/config.toml.template
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,24 @@ retainKeys = ["self_validate_jwt", "issuer", "claim_mappings", "consumer_key_cla
# If the connection is an HTTP/2 downstream connection a drain sequence will occur prior to closing the connection
idleTimeoutInSeconds = 3600

# Envoy configs relevant to circuit breaking. We can define multiple circuitBreakers for different organizations
# This should be the 1st circuit breaker
[[router.upstream.circuitBreakers]]
organizations = "*"
circuitBreakerName = "BasicCircuitBreaker"
maxConnections = 3
maxRequests = 3
maxPendingRequests = 0
maxConnectionPools = 3

[[router.upstream.circuitBreakers]]
organizations = "e0682456-2ba6-4c5f-8f36-3c5b6dc46913,4b9afefb-4bcc-4e63-85d3-ddd593841012,d3a7dfea-fb10-4371-b21d-85d1bc28667b"
circuitBreakerName = "EnhancedCircuitBreaker"
maxConnections = 50
maxRequests = 50
maxPendingRequests = 0
maxConnectionPools = 50

# Configs relevant to the envoy rate-limit service
[router.ratelimit]
# Enable/disable envoy rate-limit service
Expand Down

0 comments on commit 206a1eb

Please sign in to comment.