Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/reset api limit #114

Merged
merged 4 commits into from
Aug 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions getUserFeatureFlag/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
lambda "github.com/aws/aws-lambda-go/lambda"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/dynamodb"
"github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute"
)

func processGetById(userId string, flagId string) (*utils.FeatureFlagUserMappingResponse, error) {
Expand Down
12 changes: 6 additions & 6 deletions rateLimiterLambda/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ func handler(ctx context.Context, event json.RawMessage) (events.APIGatewayProxy
var lambdaConcurrencyValue LambdaConcurrencyValue
if err := json.Unmarshal(event, &lambdaConcurrencyValue); err != nil {
return events.APIGatewayProxyResponse{
Body: "Unable to read input",
Body: "Unable to read input",
StatusCode: http.StatusBadRequest,
}, nil
}
Expand All @@ -108,27 +108,27 @@ func handler(ctx context.Context, event json.RawMessage) (events.APIGatewayProxy
for _, functionName := range request.FunctionNames {
// Increment the WaitGroup counter
wg.Add(1)

// Start a goroutine to update the concurrency for the Lambda function
go func(fn string) {
defer wg.Done()

input := &lambda.PutFunctionConcurrencyInput{
FunctionName: &fn,
ReservedConcurrentExecutions: aws.Int64(int64(lambdaConcurrencyValue.IntValue)),
}

log.Println("Is the function name", fn)
_, err := lambdaClient.PutFunctionConcurrency(input)
if err != nil {
log.Printf("Error in setting the concurrency for the lambda name %s: %v", fn, err)
utils.ServerError(err)
}

log.Printf("Changed the reserved concurrency for the function %s to %d", fn, lambdaConcurrencyValue.IntValue)
}(functionName)
}

// Wait for all goroutines to finish
wg.Wait()
return events.APIGatewayProxyResponse{
Expand Down
3 changes: 3 additions & 0 deletions resetLimitLambda/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
build-ResetLimitFunction:
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o bootstrap
cp ./bootstrap $(ARTIFACTS_DIR)/.
16 changes: 16 additions & 0 deletions resetLimitLambda/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
module rateLimiterLambda

go 1.20

require (
github.com/Real-Dev-Squad/feature-flag-backend v0.0.0-20231002185428-1ab29298fc37
github.com/aws/aws-lambda-go v1.41.0
github.com/aws/aws-sdk-go v1.44.323
)

replace github.com/Real-Dev-Squad/feature-flag-backend => /Users/mehul/oss/feature-flag-backend

require (
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/joho/godotenv v1.5.1 // indirect
)
50 changes: 50 additions & 0 deletions resetLimitLambda/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
github.com/aws/aws-lambda-go v1.41.0 h1:l/5fyVb6Ud9uYd411xdHZzSf2n86TakxzpvIoz7l+3Y=
github.com/aws/aws-lambda-go v1.41.0/go.mod h1:jwFe2KmMsHmffA1X2R09hH6lFzJQxzI8qK17ewzbQMM=
github.com/aws/aws-sdk-go v1.44.323 h1:97/dn93DWrN1VfhAWQ2tV+xuE6oO/LO9rSsEsuC4PLU=
github.com/aws/aws-sdk-go v1.44.323/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.1.0 h1:hZ/3BUoy5aId7sCpA/Tc5lt8DkFgdVS2onTpJsZ/fl0=
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
197 changes: 197 additions & 0 deletions resetLimitLambda/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
package main

import (
"context"
"encoding/json"
"log"
"net/http"
"os"
"sync"

"github.com/Real-Dev-Squad/feature-flag-backend/database"
"github.com/Real-Dev-Squad/feature-flag-backend/models"
"github.com/Real-Dev-Squad/feature-flag-backend/utils"
"github.com/aws/aws-lambda-go/events"
lambda1 "github.com/aws/aws-lambda-go/lambda"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/dynamodb"
"github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute"
lambda "github.com/aws/aws-sdk-go/service/lambda"
)

type Request struct {
FunctionNames []string `json:"functionNames"`
}

type LambdaConcurrencyValue struct {
IntValue int `json:"intValue"`
}

type ConcurrencyLimitRequest struct {
PendingLimit int16 `json:"pendingLimit"`
}

var createFeatureFlagFunctionName string
var getUserFeatureFlagFunctionName string
var createUserFeatureFlagFunctionName string
var getAllFeatureFlagsFunctionName string
var getUserFeatureFlagsFunctionName string
var updateFeatureFlagFunctionName string
var getFeatureFlagFunctionName string
var getUserFeatureFlagFunction string
var requestLimitTableName = "requestLimit"

func init() {
env, found := os.LookupEnv(utils.ENV)
if !found {
log.Print("Env variable not set, making it by default PROD")
os.Setenv(utils.ENV, utils.PROD)
}
log.Printf("The env is %v", env)

createFeatureFlagFunctionName, found = os.LookupEnv("CreateFeatureFlagFunction")
if !found {
log.Println("Create feature flag function name not being set")
}

getUserFeatureFlagFunctionName, found = os.LookupEnv("GetUserFeatureFlagFunction")
if !found {
log.Println("Create feature flag function name not being set")
}

createUserFeatureFlagFunctionName, found = os.LookupEnv("CreateUserFeatureFlagFunction")
if !found {
log.Println("Create user feature flag function name not being set")
}

getUserFeatureFlagsFunctionName, found = os.LookupEnv("GetUserFeatureFlagsFunction")
if !found {
log.Println("get user feature flags function name not being set")
}

getAllFeatureFlagsFunctionName, found = os.LookupEnv("GetAllFeatureFlagFunction")
if !found {
log.Println("get all feature flag function name not being set")
}

updateFeatureFlagFunctionName, found = os.LookupEnv("UpdateFeatureFlagFunction")
if !found {
log.Println("Update feature flag function name not being set")
}

getFeatureFlagFunctionName, found = os.LookupEnv("GetFeatureFlagFunction")
if !found {
log.Println("get feature flag function name not being set")
}
}

func handler(ctx context.Context, event events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
var concurrencyLimitRequest ConcurrencyLimitRequest
if err := json.Unmarshal([]byte(event.Body), &concurrencyLimitRequest); err != nil {
return events.APIGatewayProxyResponse{
Body: "Unable to read input",
StatusCode: http.StatusBadRequest,
}, nil
}

sess, err := session.NewSession()
if err != nil {
log.Println("Error in creation of AWS session, please contact on #feature-flag-service discord channel.")
}
lambdaClient := lambda.New(sess)

var request = Request{
FunctionNames: []string{createFeatureFlagFunctionName,
createUserFeatureFlagFunctionName,
getFeatureFlagFunctionName,
getUserFeatureFlagFunctionName,
getAllFeatureFlagsFunctionName,
updateFeatureFlagFunctionName,
getUserFeatureFlagsFunctionName,
},
}

var wg sync.WaitGroup
for _, functionName := range request.FunctionNames {
wg.Add(1)
go func(fn string) {
defer wg.Done()
input := &lambda.DeleteFunctionConcurrencyInput{
FunctionName: &fn,
}
_, err := lambdaClient.DeleteFunctionConcurrency(input)
if err != nil {
log.Printf("Error in resetting the concurrency for the lambda name %s: %v", fn, err)
utils.ServerError(err)
}
log.Printf("Reset the reserved concurrency for the function %s", fn)
}(functionName)
}
wg.Wait()

err = updateConcurrencyLimitInDB(concurrencyLimitRequest.PendingLimit)
if err != nil {
return events.APIGatewayProxyResponse{
Body: "Failed to update concurrency limit in database",
StatusCode: http.StatusInternalServerError,
}, nil
}

return events.APIGatewayProxyResponse{
Body: "Successfully updated concurrency limit",
StatusCode: http.StatusOK,
}, nil
}

func updateConcurrencyLimitInDB(limit int16) error {
db := database.CreateDynamoDB()

requestLimitInput := &dynamodb.GetItemInput{
TableName: aws.String(requestLimitTableName),
Key: map[string]*dynamodb.AttributeValue{
"limitType": {
S: aws.String("pendingLimit"),
},
},
}

requestLimitResult, err := db.GetItem(requestLimitInput)
if err != nil {
log.Println(err, "is the error in request limit fetching")
}

requestLimitResponse := new(models.RequestLimit)
err = dynamodbattribute.UnmarshalMap(requestLimitResult.Item, requestLimitResponse)

if err != nil {
log.Println(err, "is the error")
}

requestLimitUpdateInput := models.RequestLimit{
LimitType: requestLimitResponse.LimitType,
LimitValue: limit,
}

marshalledInput, err := dynamodbattribute.MarshalMap(requestLimitUpdateInput)
if err != nil {
log.Println("Error in marshalling the request")
}

putItemInput := &dynamodb.PutItemInput{
TableName: aws.String(requestLimitTableName),
Item: marshalledInput,
}

_, err = db.PutItem(putItemInput)
if err != nil {
log.Println("Error in updating the request limit counters", err)
return nil
}
log.Println("The updated limit is ", requestLimitUpdateInput.LimitValue)
return nil
}

func main() {
lambda1.Start(handler)
}
17 changes: 17 additions & 0 deletions template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,23 @@ Resources:
Path: /mark-concurrency-zero
Method: PATCH

ResetLimitFunction:
Type: 'AWS::Serverless::Function'
Metadata:
BuildMethod: makefile
Properties:
CodeUri: resetLimitLambda/
Handler: bootstrap
Runtime: provided.al2
Architectures:
- x86_64
Events:
CatchAll:
Type: Api
Properties:
Path: /reset-limit
Method: POST

GetFeatureFlagFunction:
Type: 'AWS::Serverless::Function'
Metadata:
Expand Down
3 changes: 2 additions & 1 deletion updateUserFeatureFlag/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/dynamodb"
"github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute"
"github.com/go-playground/validator/v10"
)

Expand All @@ -29,7 +30,7 @@ func processUpdateByIds(userId string, flagId string, requestBody utils.UpdateFe
db := database.CreateDynamoDB()

utils.CheckRequestAllowed(db, utils.ConcurrencyDisablingLambda)

input := &dynamodb.UpdateItemInput{
TableName: aws.String(utils.FEATURE_FLAG_USER_MAPPING_TABLE_NAME),
Key: map[string]*dynamodb.AttributeValue{
Expand Down