Skip to content

Commit

Permalink
Merge pull request #37 from fond-of-vertigo/refactor/token-updater
Browse files Browse the repository at this point in the history
Refactor TokenUpdater to use Ticker
  • Loading branch information
adankb authored Nov 10, 2023
2 parents c0a7530 + da6ce88 commit e055866
Show file tree
Hide file tree
Showing 17 changed files with 296 additions and 176 deletions.
16 changes: 16 additions & 0 deletions .github/workflows/audit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
on: [ push, pull_request ]
name: Audit
jobs:
audit:
runs-on: ubuntu-latest
steps:
- name: Install Go
uses: actions/setup-go@v4
with:
go-version: ^1
- name: Checkout code
uses: actions/checkout@v3
- name: Run golangci-lint
uses: golangci/golangci-lint-action@v3
- name: Run tests
run: go test -race ./...
18 changes: 0 additions & 18 deletions .github/workflows/test.yml

This file was deleted.

42 changes: 19 additions & 23 deletions apis/caller.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@ package apis

import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"net/url"
"time"
Expand Down Expand Up @@ -61,8 +60,8 @@ func (a *Call[responseType]) WithRestrictedDataToken(token *string) *Call[respon
return a
}

func (a *Call[responseType]) WithParseErrorListOnError(parseErrList bool) *Call[responseType] {
a.ParseErrorListOnError = parseErrList
func (a *Call[responseType]) WithParseErrorListOnError() *Call[responseType] {
a.ParseErrorListOnError = true
return a
}

Expand All @@ -82,16 +81,24 @@ func (a *Call[responseType]) Execute(httpClient HTTPClient) (*CallResponse[respo
Status: resp.StatusCode,
}

if a.ParseErrorListOnError && !callResp.IsSuccess() {
if err = unmarshalBody(resp, &callResp.ErrorList); err != nil {
return nil, err
if callResp.IsError() {
err = fmt.Errorf("request with URL=%v returned with non-OK statuscode=%d", a.URL, callResp.Status)
if a.ParseErrorListOnError {
if parseErr := unmarshalBody(resp, &callResp.ErrorList); parseErr != nil {
return nil, errors.Join(err, parseErr)
}

return callResp, errors.Join(err, mapErrorListToError(callResp.ErrorList))
}
return callResp, nil
}
if err = unmarshalBody(resp, &callResp.ResponseBody); err != nil {
return nil, err

return callResp, err
}

if resp.ContentLength > 0 {
if err = unmarshalBody(resp, &callResp.ResponseBody); err != nil {
return nil, err
}
}
return callResp, nil
}

Expand All @@ -112,7 +119,7 @@ func (a *Call[responseType]) execute(httpClient HTTPClient) (*http.Response, err
continue
}

return resp, err
return resp, nil
}

return nil, ErrMaxRetryCountReached
Expand Down Expand Up @@ -157,17 +164,6 @@ func (r *CallResponse[any]) ErrorsAsString() string {
return msg
}

func unmarshalBody(resp *http.Response, into any) error {
bodyBytes, err := io.ReadAll(resp.Body)
if err != nil {
return err
}
if len(bodyBytes) == 0 {
return nil
}
return json.Unmarshal(bodyBytes, into)
}

func calcWaitTimeByRateLimit(callsPer float32, duration time.Duration) time.Duration {
return time.Duration(float32(duration) / callsPer)
}
30 changes: 19 additions & 11 deletions apis/caller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,10 @@ func Test_call_Execute(t *testing.T) {
},
},
},
wantErr: true,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// given:
Expand All @@ -167,8 +169,12 @@ func Test_call_Execute(t *testing.T) {
// when:
call := NewCall[dummyBody](tt.args.method, tt.args.url).
WithQueryParams(tt.args.queryParams).
WithBody(reqBodyBytes).
WithParseErrorListOnError(tt.want.resp.ErrorList != nil)
WithBody(reqBodyBytes)

if tt.want.resp.ErrorList != nil {
call = call.WithParseErrorListOnError()
}

if tt.args.restrictedDataToken != "" {
call = call.WithRestrictedDataToken(&tt.args.restrictedDataToken)
}
Expand Down Expand Up @@ -256,6 +262,7 @@ func mockResponse(callResp *CallResponse[dummyBody]) (*http.Response, error) {
if err != nil {
return nil, err
}

return &http.Response{
Status: "200 OK",
StatusCode: http.StatusOK,
Expand All @@ -279,15 +286,16 @@ func Test_calcWaitTimeByRateLimit(t *testing.T) {
name string
args args
want time.Duration
}{{
name: "0.5 req per sec, wait 2 seconds",
args: args{0.5, time.Second},
want: 2 * time.Second,
}, {
name: "2 req per sec, wait 500ms",
args: args{2, time.Second},
want: 500 * time.Millisecond,
},
}{
{
name: "0.5 req per sec, wait 2 seconds",
args: args{0.5, time.Second},
want: 2 * time.Second,
}, {
name: "2 req per sec, wait 500ms",
args: args{2, time.Second},
want: 500 * time.Millisecond,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand Down
12 changes: 6 additions & 6 deletions apis/feeds/feeds.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func NewAPI(httpClient *httpx.Client) *API {
func (a *API) GetFeeds(filter *GetFeedsRequestFilter) (*apis.CallResponse[GetFeedsResponse], error) {
return apis.NewCall[GetFeedsResponse](http.MethodGet, pathPrefix+"/feeds").
WithQueryParams(filter.GetQuery()).
WithParseErrorListOnError(true).
WithParseErrorListOnError().
WithRateLimit(0.0222, time.Second).
Execute(a.httpClient)
}
Expand All @@ -40,15 +40,15 @@ func (a *API) CreateFeed(specification *CreateFeedSpecification) (*apis.CallResp

return apis.NewCall[CreateFeedResponse](http.MethodPost, pathPrefix+"/feeds").
WithBody(body).
WithParseErrorListOnError(true).
WithParseErrorListOnError().
WithRateLimit(0.0083, time.Second).
Execute(a.httpClient)
}

// GetFeed returns feed details (including the resultDocumentId, if available) for the feed that you specify.
func (a *API) GetFeed(feedID string) (*apis.CallResponse[Feed], error) {
return apis.NewCall[Feed](http.MethodGet, pathPrefix+"/feeds/"+feedID).
WithParseErrorListOnError(true).
WithParseErrorListOnError().
WithRateLimit(2, time.Second).
Execute(a.httpClient)
}
Expand All @@ -57,7 +57,7 @@ func (a *API) GetFeed(feedID string) (*apis.CallResponse[Feed], error) {
// Cancelled feeds are returned in subsequent calls to the getFeed and getFeeds operations.
func (a *API) CancelFeed(feedID string) error {
_, err := apis.NewCall[types.Nil](http.MethodDelete, pathPrefix+"/feeds/"+feedID).
WithParseErrorListOnError(true).
WithParseErrorListOnError().
WithRateLimit(0.0222, time.Second).
Execute(a.httpClient)
return err
Expand All @@ -74,15 +74,15 @@ func (a *API) CreateFeedDocument(specification *CreateFeedDocumentSpecification)

return apis.NewCall[CreateFeedDocumentResponse](http.MethodPost, pathPrefix+"/documents").
WithBody(body).
WithParseErrorListOnError(true).
WithParseErrorListOnError().
WithRateLimit(0.0083, time.Second).
Execute(a.httpClient)
}

// GetFeedDocument the information required for retrieving a feed document's contents.
func (a *API) GetFeedDocument(feedDocumentID string) (*apis.CallResponse[FeedDocument], error) {
return apis.NewCall[FeedDocument](http.MethodGet, pathPrefix+"/documents/"+feedDocumentID).
WithParseErrorListOnError(true).
WithParseErrorListOnError().
WithRateLimit(1.0, time.Minute). // documented value (2/sec) seems way too much (many http 429 errors)
Execute(a.httpClient)
}
14 changes: 7 additions & 7 deletions apis/orders/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ var AllowedEasyShipShipmentStatus = utils.NewSet[EasyShipShipmentStatus](
)

func (v *EasyShipShipmentStatus) UnmarshalJSON(src []byte) error {
v, err := utils.UnmarshalJSONEnum[EasyShipShipmentStatus](src, AllowedEasyShipShipmentStatus)
_, err := utils.UnmarshalJSONEnum[EasyShipShipmentStatus](src, AllowedEasyShipShipmentStatus)
return err
}

Expand All @@ -185,7 +185,7 @@ var AllowedElectronicInvoiceStatus = utils.NewSet[ElectronicInvoiceStatus](
)

func (v *ElectronicInvoiceStatus) UnmarshalJSON(src []byte) error {
v, err := utils.UnmarshalJSONEnum[ElectronicInvoiceStatus](src, AllowedElectronicInvoiceStatus)
_, err := utils.UnmarshalJSONEnum[ElectronicInvoiceStatus](src, AllowedElectronicInvoiceStatus)
return err
}

Expand Down Expand Up @@ -582,7 +582,7 @@ var AllowedShipmentStatus = utils.NewSet[ShipmentStatus](
)

func (v *ShipmentStatus) UnmarshalJSON(src []byte) error {
v, err := utils.UnmarshalJSONEnum[ShipmentStatus](src, AllowedShipmentStatus)
_, err := utils.UnmarshalJSONEnum[ShipmentStatus](src, AllowedShipmentStatus)
return err
}

Expand Down Expand Up @@ -659,7 +659,7 @@ var AllowedVerificationStatus = utils.NewSet[VerificationStatus](
)

func (v *VerificationStatus) UnmarshalJSON(src []byte) error {
v, err := utils.UnmarshalJSONEnum[VerificationStatus](src, AllowedVerificationStatus)
_, err := utils.UnmarshalJSONEnum[VerificationStatus](src, AllowedVerificationStatus)
return err
}

Expand Down Expand Up @@ -825,7 +825,7 @@ const LeonardiApproval ItemApprovalType = "LEONARDI_APPROVAL"
var AllowedItemApprovalTypes = utils.NewSet[ItemApprovalType](LeonardiApproval)

func (v *ItemApprovalType) UnmarshalJSON(src []byte) error {
v, err := utils.UnmarshalJSONEnum[ItemApprovalType](src, AllowedItemApprovalTypes)
_, err := utils.UnmarshalJSONEnum[ItemApprovalType](src, AllowedItemApprovalTypes)
return err
}

Expand All @@ -850,7 +850,7 @@ var AllowedItemApprovalStatus = utils.NewSet[ItemApprovalStatus](
)

func (v *ItemApprovalStatus) UnmarshalJSON(src []byte) error {
v, err := utils.UnmarshalJSONEnum[ItemApprovalStatus](src, AllowedItemApprovalStatus)
_, err := utils.UnmarshalJSONEnum[ItemApprovalStatus](src, AllowedItemApprovalStatus)
return err
}

Expand Down Expand Up @@ -948,7 +948,7 @@ var AllowedOtherDeliveryAttributes = utils.NewSet[OtherDeliveryAttribute](
)

func (v *OtherDeliveryAttribute) UnmarshalJSON(src []byte) error {
v, err := utils.UnmarshalJSONEnum[OtherDeliveryAttribute](src, AllowedOtherDeliveryAttributes)
_, err := utils.UnmarshalJSONEnum[OtherDeliveryAttribute](src, AllowedOtherDeliveryAttributes)
return err
}

Expand Down
4 changes: 2 additions & 2 deletions apis/orders/orders.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ func (a *API) UpdateOrderItemsApprovals(orderID string, payload *UpdateOrderAppr

return apis.NewCall[types.Nil](http.MethodPost, pathPrefix+"/orders/"+orderID+"/orderItems/approvals").
WithBody(body).
WithParseErrorListOnError(true).
WithParseErrorListOnError().
WithRateLimit(5, time.Second).
Execute(a.httpClient)
}
Expand All @@ -162,7 +162,7 @@ func (a *API) ConfirmShipment(orderID string, payload *ConfirmShipmentRequest) (

return apis.NewCall[types.Nil](http.MethodPost, pathPrefix+"/orders/"+orderID+"/shipmentConfirmation").
WithBody(body).
WithParseErrorListOnError(true).
WithParseErrorListOnError().
WithRateLimit(2, time.Second).
Execute(a.httpClient)
}
14 changes: 7 additions & 7 deletions apis/reports/reports.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func (r *API) GetReports(filter *GetReportsFilter) (*apis.CallResponse[GetReport
}
return apis.NewCall[GetReportsResponse](http.MethodGet, pathPrefix+"/reports").
WithQueryParams(filter.GetQuery()).
WithParseErrorListOnError(true).
WithParseErrorListOnError().
WithRateLimit(0.0222, time.Second).
Execute(r.httpClient)
}
Expand All @@ -46,15 +46,15 @@ func (r *API) CreateReport(specification *CreateReportSpecification) (*apis.Call
}
return apis.NewCall[CreateReportResponse](http.MethodPost, pathPrefix+"/reports").
WithBody(body).
WithParseErrorListOnError(true).
WithParseErrorListOnError().
WithRateLimit(0.0167, time.Second).
Execute(r.httpClient)
}

// GetReport returns report details (including the reportDocumentID, if available) for the report that you specify.
func (r *API) GetReport(reportID string) (*apis.CallResponse[GetReportResponse], error) {
return apis.NewCall[GetReportResponse](http.MethodGet, pathPrefix+"/reports/"+reportID).
WithParseErrorListOnError(true).
WithParseErrorListOnError().
WithRateLimit(2.0, time.Second).
Execute(r.httpClient)
}
Expand All @@ -78,7 +78,7 @@ func (r *API) GetReportSchedules(reportTypes []string) (*apis.CallResponse[GetRe
params.Add("reportTypes", strings.Join(reportTypes, ","))
return apis.NewCall[GetReportsResponse](http.MethodGet, pathPrefix+"/schedules").
WithQueryParams(params).
WithParseErrorListOnError(true).
WithParseErrorListOnError().
WithRateLimit(0.0222, time.Second).
Execute(r.httpClient)
}
Expand All @@ -93,15 +93,15 @@ func (r *API) CreateReportSchedule(specification *CreateReportScheduleSpecificat
}
return apis.NewCall[CreateReportScheduleResponse](http.MethodPost, pathPrefix+"/schedules").
WithBody(body).
WithParseErrorListOnError(true).
WithParseErrorListOnError().
WithRateLimit(0.0222, time.Second).
Execute(r.httpClient)
}

// GetReportSchedule returns report schedule details for the report schedule that you specify.
func (r *API) GetReportSchedule(reportScheduleID string) (*apis.CallResponse[GetReportScheduleResponse], error) {
return apis.NewCall[GetReportScheduleResponse](http.MethodGet, pathPrefix+"/schedules/"+reportScheduleID).
WithParseErrorListOnError(true).
WithParseErrorListOnError().
WithRateLimit(0.0222, time.Second).
Execute(r.httpClient)
}
Expand All @@ -119,7 +119,7 @@ func (r *API) CancelReportSchedule(reportScheduleID string) error {
func (r *API) GetReportDocument(reportDocumentID string, restrictedDataToken *string) (*apis.CallResponse[GetReportDocumentResponse], error) {
return apis.NewCall[GetReportDocumentResponse](http.MethodGet, pathPrefix+"/documents/"+reportDocumentID).
WithRestrictedDataToken(restrictedDataToken).
WithParseErrorListOnError(true).
WithParseErrorListOnError().
WithRateLimit(0.0167, time.Second).
Execute(r.httpClient)
}
2 changes: 1 addition & 1 deletion apis/tokens/tokens.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,6 @@ func (t *API) CreateRestrictedDataTokenRequest(restrictedResources *CreateRestri
return apis.NewCall[CreateRestrictedDataTokenResponse](http.MethodPost, pathPrefix+"/restrictedDataToken").
WithBody(body).
WithRateLimit(1.0, time.Second).
WithParseErrorListOnError(true).
WithParseErrorListOnError().
Execute(t.httpClient)
}
Loading

0 comments on commit e055866

Please sign in to comment.