Skip to content

Commit

Permalink
Handle DynamoDB throughput exception (#163)
Browse files Browse the repository at this point in the history
* Handle DynamoDB throughput exception

* Prevent duplicate imports
  • Loading branch information
harryzcy authored Nov 4, 2022
1 parent c2442ad commit 574b442
Show file tree
Hide file tree
Showing 17 changed files with 74 additions and 6 deletions.
5 changes: 5 additions & 0 deletions api/emails/create/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@ func handler(ctx context.Context, req events.APIGatewayV2HTTPRequest) (apiutil.R
if err == email.ErrInvalidInput {
return apiutil.NewErrorResponse(http.StatusBadRequest, "invalid input"), nil
}
if err == email.ErrTooManyRequests {
fmt.Println("too many requests")
return apiutil.NewErrorResponse(http.StatusTooManyRequests, "too many requests"), nil
}

fmt.Printf("email create failed: %v\n", err)
return apiutil.NewErrorResponse(http.StatusInternalServerError, "internal error"), nil
}
Expand Down
4 changes: 4 additions & 0 deletions api/emails/delete/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ func handler(ctx context.Context, req events.APIGatewayV2HTTPRequest) (apiutil.R
fmt.Printf("dynamodb delete failed: %v\n", err)
return apiutil.NewErrorResponse(http.StatusBadRequest, "email not trashed"), nil
}
if err == email.ErrTooManyRequests {
fmt.Println("too many requests")
return apiutil.NewErrorResponse(http.StatusTooManyRequests, "too many requests"), nil
}

fmt.Printf("dynamodb delete failed: %v\n", err)
return apiutil.NewErrorResponse(http.StatusInternalServerError, "internal error"), nil
Expand Down
4 changes: 4 additions & 0 deletions api/emails/get/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ func handler(ctx context.Context, req events.APIGatewayV2HTTPRequest) (apiutil.R
fmt.Println("email not found")
return apiutil.NewErrorResponse(http.StatusNotFound, "email not found"), nil
}
if err == email.ErrTooManyRequests {
fmt.Println("too many requests")
return apiutil.NewErrorResponse(http.StatusTooManyRequests, "too many requests"), nil
}
fmt.Printf("dynamodb get failed: %v\n", err)
return apiutil.NewErrorResponse(http.StatusInternalServerError, "internal error"), nil
}
Expand Down
4 changes: 4 additions & 0 deletions api/emails/list/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ func handler(ctx context.Context, req events.APIGatewayV2HTTPRequest) (apiutil.R
if err == email.ErrInvalidInput {
return apiutil.NewErrorResponse(http.StatusBadRequest, "invalid input"), nil
}
if err == email.ErrTooManyRequests {
fmt.Println("too many requests")
return apiutil.NewErrorResponse(http.StatusTooManyRequests, "too many requests"), nil
}
fmt.Printf("email list failed: %v\n", err)
return apiutil.NewErrorResponse(http.StatusInternalServerError, "internal error"), nil
}
Expand Down
5 changes: 5 additions & 0 deletions api/emails/save/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,11 @@ func handler(ctx context.Context, req events.APIGatewayV2HTTPRequest) (apiutil.R
if err == email.ErrInvalidInput {
return apiutil.NewErrorResponse(http.StatusBadRequest, "invalid input"), nil
}
if err == email.ErrTooManyRequests {
fmt.Println("too many requests")
return apiutil.NewErrorResponse(http.StatusTooManyRequests, "too many requests"), nil
}

fmt.Printf("email save failed: %v\n", err)
return apiutil.NewErrorResponse(http.StatusInternalServerError, "internal error"), nil
}
Expand Down
5 changes: 5 additions & 0 deletions api/emails/send/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ func handler(ctx context.Context, req events.APIGatewayV2HTTPRequest) (apiutil.R
client := sendClient{cfg: cfg}
result, err := email.Send(ctx, client, messageID)
if err != nil {
if err == email.ErrTooManyRequests {
fmt.Println("too many requests")
return apiutil.NewErrorResponse(http.StatusTooManyRequests, "too many requests"), nil
}

fmt.Printf("email send failed: %v\n", err)
return apiutil.NewErrorResponse(http.StatusInternalServerError, "internal error"), nil
}
Expand Down
4 changes: 4 additions & 0 deletions api/emails/trash/trash.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ func handler(ctx context.Context, req events.APIGatewayV2HTTPRequest) (apiutil.R
fmt.Printf("dynamodb trash failed: %v\n", err)
return apiutil.NewErrorResponse(http.StatusBadRequest, "email is already trashed"), nil
}
if err == email.ErrTooManyRequests {
fmt.Println("too many requests")
return apiutil.NewErrorResponse(http.StatusTooManyRequests, "too many requests"), nil
}

fmt.Printf("dynamodb trash failed: %v\n", err)
return apiutil.NewErrorResponse(http.StatusInternalServerError, "internal error"), nil
Expand Down
4 changes: 4 additions & 0 deletions api/emails/untrash/untrash.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ func handler(ctx context.Context, req events.APIGatewayV2HTTPRequest) (apiutil.R
fmt.Printf("dynamodb untrash failed: %v\n", err)
return apiutil.NewErrorResponse(http.StatusBadRequest, "email already not trashed"), nil
}
if err == email.ErrTooManyRequests {
fmt.Println("too many requests")
return apiutil.NewErrorResponse(http.StatusTooManyRequests, "too many requests"), nil
}

fmt.Printf("dynamodb untrash failed: %v\n", err)
return apiutil.NewErrorResponse(http.StatusInternalServerError, "internal error"), nil
Expand Down
5 changes: 5 additions & 0 deletions internal/email/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ package email

import (
"context"
"errors"
"fmt"
"strings"
"time"

"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/dynamodb"
"github.com/aws/aws-sdk-go-v2/service/dynamodb/types"
"github.com/google/uuid"
"github.com/harryzcy/mailbox/internal/util/htmlutil"
)
Expand Down Expand Up @@ -64,6 +66,9 @@ func Create(ctx context.Context, api SaveAndSendEmailAPI, input CreateInput) (*C
Item: item,
})
if err != nil {
if apiErr := new(types.ProvisionedThroughputExceededException); errors.As(err, &apiErr) {
return nil, ErrTooManyRequests
}
return nil, err
}

Expand Down
3 changes: 3 additions & 0 deletions internal/email/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ func Delete(ctx context.Context, api DeleteItemAPI, messageID string) error {

err = storage.S3.DeleteEmail(ctx, api, messageID)
if err != nil {
if apiErr := new(types.ProvisionedThroughputExceededException); errors.As(err, &apiErr) {
return ErrTooManyRequests
}
return err
}

Expand Down
2 changes: 2 additions & 0 deletions internal/email/err.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import "errors"

// Errors
var (
ErrTooManyRequests = errors.New("too many requests")

ErrNotFound = errors.New("email not found")
ErrInvalidInput = errors.New("invalid input")
ErrQueryNotMatch = errors.New("query does not match with next cursor")
Expand Down
4 changes: 4 additions & 0 deletions internal/email/get.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package email

import (
"context"
"errors"
"fmt"

"github.com/aws/aws-sdk-go-v2/aws"
Expand Down Expand Up @@ -43,6 +44,9 @@ func Get(ctx context.Context, api GetItemAPI, messageID string) (*GetResult, err
},
})
if err != nil {
if apiErr := new(types.ProvisionedThroughputExceededException); errors.As(err, &apiErr) {
return nil, ErrTooManyRequests
}
return nil, err
}
if len(resp.Item) == 0 {
Expand Down
5 changes: 5 additions & 0 deletions internal/email/list_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package email

import (
"context"
"errors"
"fmt"

"github.com/aws/aws-sdk-go-v2/aws"
Expand Down Expand Up @@ -50,6 +51,10 @@ func listByYearMonth(ctx context.Context, api QueryAPI, input listQueryInput) (l
ScanIndexForward: aws.Bool(false), // reverse order
})
if err != nil {
if apiErr := new(types.ProvisionedThroughputExceededException); errors.As(err, &apiErr) {
return listQueryResult{}, ErrTooManyRequests
}

return listQueryResult{}, err
}

Expand Down
7 changes: 5 additions & 2 deletions internal/email/save.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,13 @@ func Save(ctx context.Context, api SaveAndSendEmailAPI, input SaveInput) (*SaveR
},
})
if err != nil {
var condFailedErr *types.ConditionalCheckFailedException
if errors.As(err, &condFailedErr) {
if apiErr := new(types.ConditionalCheckFailedException); errors.As(err, &apiErr) {
return nil, ErrNotFound
}
if apiErr := new(types.ProvisionedThroughputExceededException); errors.As(err, &apiErr) {
return nil, ErrTooManyRequests
}

return nil, err
}

Expand Down
4 changes: 4 additions & 0 deletions internal/email/send.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package email

import (
"context"
"errors"
"fmt"
"strings"

Expand Down Expand Up @@ -119,6 +120,9 @@ func markEmailAsSent(ctx context.Context, api SendEmailAPI, oldMessageID string,
})

if err != nil {
if apiErr := new(dynamodbtypes.ProvisionedThroughputExceededException); errors.As(err, &apiErr) {
return ErrTooManyRequests
}
return err
}
return nil
Expand Down
7 changes: 5 additions & 2 deletions internal/email/trash.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,13 @@ func Trash(ctx context.Context, api UpdateItemAPI, messageID string) error {
},
})
if err != nil {
var condFailedErr *types.ConditionalCheckFailedException
if errors.As(err, &condFailedErr) {
if apiErr := new(types.ConditionalCheckFailedException); errors.As(err, &apiErr) {
return ErrAlreadyTrashed
}
if apiErr := new(types.ProvisionedThroughputExceededException); errors.As(err, &apiErr) {
return ErrTooManyRequests
}

return err
}

Expand Down
8 changes: 6 additions & 2 deletions internal/email/untrash.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,14 @@ func Untrash(ctx context.Context, api UpdateItemAPI, messageID string) error {
},
})
if err != nil {
var condFailedErr *types.ConditionalCheckFailedException
if errors.As(err, &condFailedErr) {
if apiErr := new(types.ConditionalCheckFailedException); errors.As(err, &apiErr) {
return ErrNotTrashed
}

if apiErr := new(types.ProvisionedThroughputExceededException); errors.As(err, &apiErr) {
return ErrTooManyRequests
}

return err
}

Expand Down

0 comments on commit 574b442

Please sign in to comment.