diff --git a/.openapi-generator/FILES b/.openapi-generator/FILES index beaac34..44faa63 100644 --- a/.openapi-generator/FILES +++ b/.openapi-generator/FILES @@ -25,6 +25,7 @@ docs/AbortedMessageResponse.md docs/Any.md docs/Assertion.md docs/AssertionTupleKey.md +docs/AuthErrorCode.md docs/AuthorizationModel.md docs/CheckRequest.md docs/CheckRequestTupleKey.md @@ -43,6 +44,7 @@ docs/ExpandRequest.md docs/ExpandRequestTupleKey.md docs/ExpandResponse.md docs/FgaObject.md +docs/ForbiddenResponse.md docs/GetStoreResponse.md docs/InternalErrorCode.md docs/InternalErrorMessageResponse.md @@ -111,13 +113,17 @@ example/opentelemetry/main.go git_push.sh go.mod go.sum -internal/utils/randomtime.go +internal/utils/retryutils/retryparams.go +internal/utils/retryutils/retryparams_test.go +internal/utils/retryutils/retryutils.go +internal/utils/retryutils/retryutils_test.go internal/utils/ulid.go internal/utils/ulid_test.go model_aborted_message_response.go model_any.go model_assertion.go model_assertion_tuple_key.go +model_auth_error_code.go model_authorization_model.go model_check_request.go model_check_request_tuple_key.go @@ -136,6 +142,7 @@ model_expand_request.go model_expand_request_tuple_key.go model_expand_response.go model_fga_object.go +model_forbidden_response.go model_get_store_response.go model_internal_error_code.go model_internal_error_message_response.go diff --git a/CHANGELOG.md b/CHANGELOG.md index f2c2ad0..4d83284 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [Unreleased](https://github.com/openfga/go-sdk/compare/v0.6.5...HEAD) + +- feat: fix and improve retries and rate limit handling. (#176) + The SDK now retries on network errors and the default retry handling has been fixed + for both the calls to the OpenFGA API and the API Token Issuer for those using ClientCredentials + The SDK now also respects the rate limit headers (`Retry-After`) returned by the server and will retry the request after the specified time. + If the header is not sent or on network errors, it will fall back to exponential backoff. + ## v0.6.5 ### [0.6.5](https://github.com/openfga/go-sdk/compare/v0.6.4...v0.6.5) (2025-02-06) diff --git a/README.md b/README.md index a495350..9412299 100644 --- a/README.md +++ b/README.md @@ -1061,7 +1061,7 @@ If you have found a bug or if you have a feature request, please report them on ### Pull Requests -While we accept Pull Requests on this repository, the SDKs are autogenerated so please consider additionally submitting your Pull Requests to the [sdk-generator](https://github.com/openfga/sdk-generator) and linking the two PRs together and to the corresponding issue. This will greatly assist the OpenFGA team in being able to give timely reviews as well as deploying fixes and updates to our other SDKs as well. +While we accept Pull Requests on this repository, the SDKs are autogenerated so please consider additionally submitting your Pull Requests to the [sdk-generator](https://github.com/openfga/sdk-generator) and linking the two PRs together and to the corresponding issue. This will greatly assist the OpenFGA team in being able to give timely reviews as well as deploying fixes and updates to our other SDKs as well. ## Author diff --git a/api_client.go b/api_client.go index 42c47a1..8f996ee 100644 --- a/api_client.go +++ b/api_client.go @@ -31,6 +31,7 @@ import ( "time" "unicode/utf8" + "github.com/openfga/go-sdk/internal/utils/retryutils" "github.com/openfga/go-sdk/telemetry" ) @@ -74,7 +75,7 @@ func NewAPIClient(cfg *Configuration) *APIClient { } else { cfg.Credentials.Context = context.Background() telemetry.Bind(cfg.Credentials.Context, telemetry.Get(telemetry.TelemetryFactoryParameters{Configuration: cfg.Telemetry})) - var httpClient, headers = cfg.Credentials.GetHttpClientAndHeaderOverrides() + var httpClient, headers = cfg.Credentials.GetHttpClientAndHeaderOverrides(retryutils.GetRetryParamsOrDefault(cfg.RetryParams)) if len(headers) > 0 { for idx := range headers { cfg.AddDefaultHeader(headers[idx].Key, headers[idx].Value) diff --git a/api_open_fga.go b/api_open_fga.go index 00cc495..63d998a 100644 --- a/api_open_fga.go +++ b/api_open_fga.go @@ -14,20 +14,20 @@ package openfga import ( "bytes" - _context "context" - _ioutil "io/ioutil" - _nethttp "net/http" - _neturl "net/url" + "context" + "io" + "net/http" + "net/url" "strings" "time" - internalutils "github.com/openfga/go-sdk/internal/utils" - telemetry "github.com/openfga/go-sdk/telemetry" + "github.com/openfga/go-sdk/internal/utils/retryutils" + "github.com/openfga/go-sdk/telemetry" ) // Linger please var ( - _ _context.Context + _ context.Context ) type OpenFgaApi interface { @@ -153,45 +153,45 @@ type OpenFgaApi interface { } ``` - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). * @param storeId * @return ApiCheckRequest */ - Check(ctx _context.Context, storeId string) ApiCheckRequest + Check(ctx context.Context, storeId string) ApiCheckRequest /* * CheckExecute executes the request * @return CheckResponse */ - CheckExecute(r ApiCheckRequest) (CheckResponse, *_nethttp.Response, error) + CheckExecute(r ApiCheckRequest) (CheckResponse, *http.Response, error) /* * CreateStore Create a store * Create a unique OpenFGA store which will be used to store authorization models and relationship tuples. - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). * @return ApiCreateStoreRequest */ - CreateStore(ctx _context.Context) ApiCreateStoreRequest + CreateStore(ctx context.Context) ApiCreateStoreRequest /* * CreateStoreExecute executes the request * @return CreateStoreResponse */ - CreateStoreExecute(r ApiCreateStoreRequest) (CreateStoreResponse, *_nethttp.Response, error) + CreateStoreExecute(r ApiCreateStoreRequest) (CreateStoreResponse, *http.Response, error) /* * DeleteStore Delete a store * Delete an OpenFGA store. This does not delete the data associated with the store, like tuples or authorization models. - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). * @param storeId * @return ApiDeleteStoreRequest */ - DeleteStore(ctx _context.Context, storeId string) ApiDeleteStoreRequest + DeleteStore(ctx context.Context, storeId string) ApiDeleteStoreRequest /* * DeleteStoreExecute executes the request */ - DeleteStoreExecute(r ApiDeleteStoreRequest) (*_nethttp.Response, error) + DeleteStoreExecute(r ApiDeleteStoreRequest) (*http.Response, error) /* * Expand Expand all relationships in userset tree format, and following userset rewrite rules. Useful to reason about and debug a certain relationship @@ -244,32 +244,32 @@ type OpenFgaApi interface { } ``` The caller can then call expand API for the `writer` relationship for the `document:2021-budget`. - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). * @param storeId * @return ApiExpandRequest */ - Expand(ctx _context.Context, storeId string) ApiExpandRequest + Expand(ctx context.Context, storeId string) ApiExpandRequest /* * ExpandExecute executes the request * @return ExpandResponse */ - ExpandExecute(r ApiExpandRequest) (ExpandResponse, *_nethttp.Response, error) + ExpandExecute(r ApiExpandRequest) (ExpandResponse, *http.Response, error) /* * GetStore Get a store * Returns an OpenFGA store by its identifier - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). * @param storeId * @return ApiGetStoreRequest */ - GetStore(ctx _context.Context, storeId string) ApiGetStoreRequest + GetStore(ctx context.Context, storeId string) ApiGetStoreRequest /* * GetStoreExecute executes the request * @return GetStoreResponse */ - GetStoreExecute(r ApiGetStoreRequest) (GetStoreResponse, *_nethttp.Response, error) + GetStoreExecute(r ApiGetStoreRequest) (GetStoreResponse, *http.Response, error) /* * ListObjects List all objects of the given type that the user has a relation with @@ -282,33 +282,33 @@ type OpenFgaApi interface { The response will contain the related objects in an array in the "objects" field of the response and they will be strings in the object format `:` (e.g. "document:roadmap"). The number of objects in the response array will be limited by the execution timeout specified in the flag OPENFGA_LIST_OBJECTS_DEADLINE and by the upper bound specified in the flag OPENFGA_LIST_OBJECTS_MAX_RESULTS, whichever is hit first. The objects given will not be sorted, and therefore two identical calls can give a given different set of objects. - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). * @param storeId * @return ApiListObjectsRequest */ - ListObjects(ctx _context.Context, storeId string) ApiListObjectsRequest + ListObjects(ctx context.Context, storeId string) ApiListObjectsRequest /* * ListObjectsExecute executes the request * @return ListObjectsResponse */ - ListObjectsExecute(r ApiListObjectsRequest) (ListObjectsResponse, *_nethttp.Response, error) + ListObjectsExecute(r ApiListObjectsRequest) (ListObjectsResponse, *http.Response, error) /* * ListStores List all stores * Returns a paginated list of OpenFGA stores and a continuation token to get additional stores. The continuation token will be empty if there are no more stores. - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). * @return ApiListStoresRequest */ - ListStores(ctx _context.Context) ApiListStoresRequest + ListStores(ctx context.Context) ApiListStoresRequest /* * ListStoresExecute executes the request * @return ListStoresResponse */ - ListStoresExecute(r ApiListStoresRequest) (ListStoresResponse, *_nethttp.Response, error) + ListStoresExecute(r ApiListStoresRequest) (ListStoresResponse, *http.Response, error) /* * ListUsers List the users matching the provided filter who have a certain relation to a particular type. @@ -322,17 +322,17 @@ type OpenFgaApi interface { of that type have a relation to the object; it is possible that negations exist and checks should still be queried on individual subjects to ensure access to that document.The number of users in the response array will be limited by the execution timeout specified in the flag OPENFGA_LIST_USERS_DEADLINE and by the upper bound specified in the flag OPENFGA_LIST_USERS_MAX_RESULTS, whichever is hit first. The returned users will not be sorted, and therefore two identical calls may yield different sets of users. - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). * @param storeId * @return ApiListUsersRequest */ - ListUsers(ctx _context.Context, storeId string) ApiListUsersRequest + ListUsers(ctx context.Context, storeId string) ApiListUsersRequest /* * ListUsersExecute executes the request * @return ListUsersResponse */ - ListUsersExecute(r ApiListUsersRequest) (ListUsersResponse, *_nethttp.Response, error) + ListUsersExecute(r ApiListUsersRequest) (ListUsersResponse, *http.Response, error) /* * Read Get tuples from the store that matches a query, without following userset rewrite rules @@ -435,33 +435,33 @@ type OpenFgaApi interface { ``` This means that `document:2021-budget` has 1 `reader` (`user:bob`) and 1 `writer` (`user:anne`). - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). * @param storeId * @return ApiReadRequest */ - Read(ctx _context.Context, storeId string) ApiReadRequest + Read(ctx context.Context, storeId string) ApiReadRequest /* * ReadExecute executes the request * @return ReadResponse */ - ReadExecute(r ApiReadRequest) (ReadResponse, *_nethttp.Response, error) + ReadExecute(r ApiReadRequest) (ReadResponse, *http.Response, error) /* * ReadAssertions Read assertions for an authorization model ID * The ReadAssertions API will return, for a given authorization model id, all the assertions stored for it. - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). * @param storeId * @param authorizationModelId * @return ApiReadAssertionsRequest */ - ReadAssertions(ctx _context.Context, storeId string, authorizationModelId string) ApiReadAssertionsRequest + ReadAssertions(ctx context.Context, storeId string, authorizationModelId string) ApiReadAssertionsRequest /* * ReadAssertionsExecute executes the request * @return ReadAssertionsResponse */ - ReadAssertionsExecute(r ApiReadAssertionsRequest) (ReadAssertionsResponse, *_nethttp.Response, error) + ReadAssertionsExecute(r ApiReadAssertionsRequest) (ReadAssertionsResponse, *http.Response, error) /* * ReadAuthorizationModel Return a particular version of an authorization model @@ -506,18 +506,18 @@ type OpenFgaApi interface { } ``` In the above example, there are 2 types (`user` and `document`). The `document` type has 2 relations (`writer` and `reader`). - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). * @param storeId * @param id * @return ApiReadAuthorizationModelRequest */ - ReadAuthorizationModel(ctx _context.Context, storeId string, id string) ApiReadAuthorizationModelRequest + ReadAuthorizationModel(ctx context.Context, storeId string, id string) ApiReadAuthorizationModelRequest /* * ReadAuthorizationModelExecute executes the request * @return ReadAuthorizationModelResponse */ - ReadAuthorizationModelExecute(r ApiReadAuthorizationModelRequest) (ReadAuthorizationModelResponse, *_nethttp.Response, error) + ReadAuthorizationModelExecute(r ApiReadAuthorizationModelRequest) (ReadAuthorizationModelResponse, *http.Response, error) /* * ReadAuthorizationModels Return all the authorization models for a particular store @@ -558,17 +558,17 @@ type OpenFgaApi interface { } ``` - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). * @param storeId * @return ApiReadAuthorizationModelsRequest */ - ReadAuthorizationModels(ctx _context.Context, storeId string) ApiReadAuthorizationModelsRequest + ReadAuthorizationModels(ctx context.Context, storeId string) ApiReadAuthorizationModelsRequest /* * ReadAuthorizationModelsExecute executes the request * @return ReadAuthorizationModelsResponse */ - ReadAuthorizationModelsExecute(r ApiReadAuthorizationModelsRequest) (ReadAuthorizationModelsResponse, *_nethttp.Response, error) + ReadAuthorizationModelsExecute(r ApiReadAuthorizationModelsRequest) (ReadAuthorizationModelsResponse, *http.Response, error) /* * ReadChanges Return a list of all the tuple changes @@ -577,17 +577,17 @@ type OpenFgaApi interface { When reading a write tuple change, if it was conditioned, the condition will be returned. When reading a delete tuple change, the condition will NOT be returned regardless of whether it was originally conditioned or not. - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). * @param storeId * @return ApiReadChangesRequest */ - ReadChanges(ctx _context.Context, storeId string) ApiReadChangesRequest + ReadChanges(ctx context.Context, storeId string) ApiReadChangesRequest /* * ReadChangesExecute executes the request * @return ReadChangesResponse */ - ReadChangesExecute(r ApiReadChangesRequest) (ReadChangesResponse, *_nethttp.Response, error) + ReadChangesExecute(r ApiReadChangesRequest) (ReadChangesResponse, *http.Response, error) /* * Write Add or delete tuples from the store @@ -629,32 +629,32 @@ type OpenFgaApi interface { } ``` - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). * @param storeId * @return ApiWriteRequest */ - Write(ctx _context.Context, storeId string) ApiWriteRequest + Write(ctx context.Context, storeId string) ApiWriteRequest /* * WriteExecute executes the request * @return map[string]interface{} */ - WriteExecute(r ApiWriteRequest) (map[string]interface{}, *_nethttp.Response, error) + WriteExecute(r ApiWriteRequest) (map[string]interface{}, *http.Response, error) /* * WriteAssertions Upsert assertions for an authorization model ID * The WriteAssertions API will upsert new assertions for an authorization model id, or overwrite the existing ones. An assertion is an object that contains a tuple key, the expectation of whether a call to the Check API of that tuple key will return true or false, and optionally a list of contextual tuples. - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). * @param storeId * @param authorizationModelId * @return ApiWriteAssertionsRequest */ - WriteAssertions(ctx _context.Context, storeId string, authorizationModelId string) ApiWriteAssertionsRequest + WriteAssertions(ctx context.Context, storeId string, authorizationModelId string) ApiWriteAssertionsRequest /* * WriteAssertionsExecute executes the request */ - WriteAssertionsExecute(r ApiWriteAssertionsRequest) (*_nethttp.Response, error) + WriteAssertionsExecute(r ApiWriteAssertionsRequest) (*http.Response, error) /* * WriteAuthorizationModel Create a new authorization model @@ -701,24 +701,24 @@ type OpenFgaApi interface { {"authorization_model_id": "01G50QVV17PECNVAHX1GG4Y5NC"} ``` - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). * @param storeId * @return ApiWriteAuthorizationModelRequest */ - WriteAuthorizationModel(ctx _context.Context, storeId string) ApiWriteAuthorizationModelRequest + WriteAuthorizationModel(ctx context.Context, storeId string) ApiWriteAuthorizationModelRequest /* * WriteAuthorizationModelExecute executes the request * @return WriteAuthorizationModelResponse */ - WriteAuthorizationModelExecute(r ApiWriteAuthorizationModelRequest) (WriteAuthorizationModelResponse, *_nethttp.Response, error) + WriteAuthorizationModelExecute(r ApiWriteAuthorizationModelRequest) (WriteAuthorizationModelResponse, *http.Response, error) } // OpenFgaApiService OpenFgaApi service type OpenFgaApiService service type ApiCheckRequest struct { - ctx _context.Context + ctx context.Context ApiService OpenFgaApi storeId string body *CheckRequest @@ -729,7 +729,7 @@ func (r ApiCheckRequest) Body(body CheckRequest) ApiCheckRequest { return r } -func (r ApiCheckRequest) Execute() (CheckResponse, *_nethttp.Response, error) { +func (r ApiCheckRequest) Execute() (CheckResponse, *http.Response, error) { return r.ApiService.CheckExecute(r) } @@ -875,11 +875,11 @@ By default, the Check API caches results for a short time to optimize performanc ``` - - @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @param storeId - @return ApiCheckRequest */ -func (a *OpenFgaApiService) Check(ctx _context.Context, storeId string) ApiCheckRequest { +func (a *OpenFgaApiService) Check(ctx context.Context, storeId string) ApiCheckRequest { return ApiCheckRequest{ ApiService: a, ctx: ctx, @@ -891,22 +891,13 @@ func (a *OpenFgaApiService) Check(ctx _context.Context, storeId string) ApiCheck * Execute executes the request * @return CheckResponse */ -func (a *OpenFgaApiService) CheckExecute(r ApiCheckRequest) (CheckResponse, *_nethttp.Response, error) { - var maxRetry int - var minWaitInMs int - var requestStarted time.Time = time.Now() - - if a.RetryParams != nil { - maxRetry = a.RetryParams.MinWaitInMs - minWaitInMs = a.RetryParams.MinWaitInMs - } else { - maxRetry = 0 - minWaitInMs = 0 - } +func (a *OpenFgaApiService) CheckExecute(r ApiCheckRequest) (CheckResponse, *http.Response, error) { + var requestStarted = time.Now() - for i := 0; i < maxRetry+1; i++ { + retryParams := a.client.cfg.RetryParams + for i := 0; i < retryParams.MaxRetry+1; i++ { var ( - localVarHTTPMethod = _nethttp.MethodPost + localVarHTTPMethod = http.MethodPost localVarPostBody interface{} localVarReturnValue CheckResponse ) @@ -916,10 +907,10 @@ func (a *OpenFgaApiService) CheckExecute(r ApiCheckRequest) (CheckResponse, *_ne return localVarReturnValue, nil, reportError("storeId is required and must be specified") } - localVarPath = strings.Replace(localVarPath, "{"+"store_id"+"}", _neturl.PathEscape(parameterToString(r.storeId, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"store_id"+"}", url.PathEscape(parameterToString(r.storeId, "")), -1) localVarHeaderParams := make(map[string]string) - localVarQueryParams := _neturl.Values{} + localVarQueryParams := url.Values{} if r.body == nil { return localVarReturnValue, nil, reportError("body is required and must be specified") } @@ -950,19 +941,33 @@ func (a *OpenFgaApiService) CheckExecute(r ApiCheckRequest) (CheckResponse, *_ne localVarHTTPResponse, err := a.client.callAPI(req) if err != nil || localVarHTTPResponse == nil { + if i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, http.Header{}, "Check") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } + } return localVarReturnValue, localVarHTTPResponse, err } - localVarBody, err := _ioutil.ReadAll(localVarHTTPResponse.Body) + localVarBody, err := io.ReadAll(localVarHTTPResponse.Body) localVarHTTPResponse.Body.Close() - localVarHTTPResponse.Body = _ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + localVarHTTPResponse.Body = io.NopCloser(bytes.NewBuffer(localVarBody)) if err != nil { + if i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, localVarHTTPResponse.Header, "Check") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } + } return localVarReturnValue, localVarHTTPResponse, err } - if localVarHTTPResponse.StatusCode >= _nethttp.StatusMultipleChoices { + if localVarHTTPResponse.StatusCode >= http.StatusMultipleChoices { - if localVarHTTPResponse.StatusCode == _nethttp.StatusBadRequest || localVarHTTPResponse.StatusCode == _nethttp.StatusUnprocessableEntity { + if localVarHTTPResponse.StatusCode == http.StatusBadRequest || localVarHTTPResponse.StatusCode == http.StatusUnprocessableEntity { newErr := FgaApiValidationError{ body: localVarBody, storeId: r.storeId, @@ -988,7 +993,7 @@ func (a *OpenFgaApiService) CheckExecute(r ApiCheckRequest) (CheckResponse, *_ne return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == _nethttp.StatusUnauthorized || localVarHTTPResponse.StatusCode == _nethttp.StatusForbidden { + if localVarHTTPResponse.StatusCode == http.StatusUnauthorized || localVarHTTPResponse.StatusCode == http.StatusForbidden { newErr := FgaApiAuthenticationError{ body: localVarBody, storeId: r.storeId, @@ -1003,7 +1008,7 @@ func (a *OpenFgaApiService) CheckExecute(r ApiCheckRequest) (CheckResponse, *_ne return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == _nethttp.StatusNotFound { + if localVarHTTPResponse.StatusCode == http.StatusNotFound { newErr := FgaApiNotFoundError{ body: localVarBody, storeId: r.storeId, @@ -1029,10 +1034,13 @@ func (a *OpenFgaApiService) CheckExecute(r ApiCheckRequest) (CheckResponse, *_ne return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == _nethttp.StatusTooManyRequests { - if i < maxRetry { - time.Sleep(time.Duration(internalutils.RandomTime(i, minWaitInMs)) * time.Millisecond) - continue + if localVarHTTPResponse.StatusCode == http.StatusTooManyRequests { + if i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, localVarHTTPResponse.Header, "Check") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } } // maximum number of retry reached newErr := FgaApiRateLimitExceededError{ @@ -1051,10 +1059,13 @@ func (a *OpenFgaApiService) CheckExecute(r ApiCheckRequest) (CheckResponse, *_ne return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode >= _nethttp.StatusInternalServerError { - if localVarHTTPResponse.StatusCode != _nethttp.StatusNotImplemented && i < maxRetry { - time.Sleep(time.Duration(internalutils.RandomTime(i, minWaitInMs)) * time.Millisecond) - continue + if localVarHTTPResponse.StatusCode >= http.StatusInternalServerError { + if localVarHTTPResponse.StatusCode != http.StatusNotImplemented && i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, localVarHTTPResponse.Header, "Check") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } } newErr := FgaApiInternalError{ body: localVarBody, @@ -1144,7 +1155,7 @@ func (a *OpenFgaApiService) CheckExecute(r ApiCheckRequest) (CheckResponse, *_ne } type ApiCreateStoreRequest struct { - ctx _context.Context + ctx context.Context ApiService OpenFgaApi body *CreateStoreRequest } @@ -1154,17 +1165,17 @@ func (r ApiCreateStoreRequest) Body(body CreateStoreRequest) ApiCreateStoreReque return r } -func (r ApiCreateStoreRequest) Execute() (CreateStoreResponse, *_nethttp.Response, error) { +func (r ApiCreateStoreRequest) Execute() (CreateStoreResponse, *http.Response, error) { return r.ApiService.CreateStoreExecute(r) } /* * CreateStore Create a store * Create a unique OpenFGA store which will be used to store authorization models and relationship tuples. - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). * @return ApiCreateStoreRequest */ -func (a *OpenFgaApiService) CreateStore(ctx _context.Context) ApiCreateStoreRequest { +func (a *OpenFgaApiService) CreateStore(ctx context.Context) ApiCreateStoreRequest { return ApiCreateStoreRequest{ ApiService: a, ctx: ctx, @@ -1175,22 +1186,13 @@ func (a *OpenFgaApiService) CreateStore(ctx _context.Context) ApiCreateStoreRequ * Execute executes the request * @return CreateStoreResponse */ -func (a *OpenFgaApiService) CreateStoreExecute(r ApiCreateStoreRequest) (CreateStoreResponse, *_nethttp.Response, error) { - var maxRetry int - var minWaitInMs int - var requestStarted time.Time = time.Now() - - if a.RetryParams != nil { - maxRetry = a.RetryParams.MinWaitInMs - minWaitInMs = a.RetryParams.MinWaitInMs - } else { - maxRetry = 0 - minWaitInMs = 0 - } +func (a *OpenFgaApiService) CreateStoreExecute(r ApiCreateStoreRequest) (CreateStoreResponse, *http.Response, error) { + var requestStarted = time.Now() - for i := 0; i < maxRetry+1; i++ { + retryParams := a.client.cfg.RetryParams + for i := 0; i < retryParams.MaxRetry+1; i++ { var ( - localVarHTTPMethod = _nethttp.MethodPost + localVarHTTPMethod = http.MethodPost localVarPostBody interface{} localVarReturnValue CreateStoreResponse ) @@ -1198,7 +1200,7 @@ func (a *OpenFgaApiService) CreateStoreExecute(r ApiCreateStoreRequest) (CreateS localVarPath := "/stores" localVarHeaderParams := make(map[string]string) - localVarQueryParams := _neturl.Values{} + localVarQueryParams := url.Values{} if r.body == nil { return localVarReturnValue, nil, reportError("body is required and must be specified") } @@ -1229,19 +1231,33 @@ func (a *OpenFgaApiService) CreateStoreExecute(r ApiCreateStoreRequest) (CreateS localVarHTTPResponse, err := a.client.callAPI(req) if err != nil || localVarHTTPResponse == nil { + if i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, http.Header{}, "CreateStore") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } + } return localVarReturnValue, localVarHTTPResponse, err } - localVarBody, err := _ioutil.ReadAll(localVarHTTPResponse.Body) + localVarBody, err := io.ReadAll(localVarHTTPResponse.Body) localVarHTTPResponse.Body.Close() - localVarHTTPResponse.Body = _ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + localVarHTTPResponse.Body = io.NopCloser(bytes.NewBuffer(localVarBody)) if err != nil { + if i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, localVarHTTPResponse.Header, "CreateStore") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } + } return localVarReturnValue, localVarHTTPResponse, err } - if localVarHTTPResponse.StatusCode >= _nethttp.StatusMultipleChoices { + if localVarHTTPResponse.StatusCode >= http.StatusMultipleChoices { - if localVarHTTPResponse.StatusCode == _nethttp.StatusBadRequest || localVarHTTPResponse.StatusCode == _nethttp.StatusUnprocessableEntity { + if localVarHTTPResponse.StatusCode == http.StatusBadRequest || localVarHTTPResponse.StatusCode == http.StatusUnprocessableEntity { newErr := FgaApiValidationError{ body: localVarBody, endpointCategory: "CreateStore", @@ -1266,7 +1282,7 @@ func (a *OpenFgaApiService) CreateStoreExecute(r ApiCreateStoreRequest) (CreateS return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == _nethttp.StatusUnauthorized || localVarHTTPResponse.StatusCode == _nethttp.StatusForbidden { + if localVarHTTPResponse.StatusCode == http.StatusUnauthorized || localVarHTTPResponse.StatusCode == http.StatusForbidden { newErr := FgaApiAuthenticationError{ body: localVarBody, endpointCategory: "CreateStore", @@ -1280,7 +1296,7 @@ func (a *OpenFgaApiService) CreateStoreExecute(r ApiCreateStoreRequest) (CreateS return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == _nethttp.StatusNotFound { + if localVarHTTPResponse.StatusCode == http.StatusNotFound { newErr := FgaApiNotFoundError{ body: localVarBody, endpointCategory: "CreateStore", @@ -1305,10 +1321,13 @@ func (a *OpenFgaApiService) CreateStoreExecute(r ApiCreateStoreRequest) (CreateS return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == _nethttp.StatusTooManyRequests { - if i < maxRetry { - time.Sleep(time.Duration(internalutils.RandomTime(i, minWaitInMs)) * time.Millisecond) - continue + if localVarHTTPResponse.StatusCode == http.StatusTooManyRequests { + if i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, localVarHTTPResponse.Header, "CreateStore") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } } // maximum number of retry reached newErr := FgaApiRateLimitExceededError{ @@ -1326,10 +1345,13 @@ func (a *OpenFgaApiService) CreateStoreExecute(r ApiCreateStoreRequest) (CreateS return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode >= _nethttp.StatusInternalServerError { - if localVarHTTPResponse.StatusCode != _nethttp.StatusNotImplemented && i < maxRetry { - time.Sleep(time.Duration(internalutils.RandomTime(i, minWaitInMs)) * time.Millisecond) - continue + if localVarHTTPResponse.StatusCode >= http.StatusInternalServerError { + if localVarHTTPResponse.StatusCode != http.StatusNotImplemented && i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, localVarHTTPResponse.Header, "CreateStore") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } } newErr := FgaApiInternalError{ body: localVarBody, @@ -1416,23 +1438,23 @@ func (a *OpenFgaApiService) CreateStoreExecute(r ApiCreateStoreRequest) (CreateS } type ApiDeleteStoreRequest struct { - ctx _context.Context + ctx context.Context ApiService OpenFgaApi storeId string } -func (r ApiDeleteStoreRequest) Execute() (*_nethttp.Response, error) { +func (r ApiDeleteStoreRequest) Execute() (*http.Response, error) { return r.ApiService.DeleteStoreExecute(r) } /* * DeleteStore Delete a store * Delete an OpenFGA store. This does not delete the data associated with the store, like tuples or authorization models. - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). * @param storeId * @return ApiDeleteStoreRequest */ -func (a *OpenFgaApiService) DeleteStore(ctx _context.Context, storeId string) ApiDeleteStoreRequest { +func (a *OpenFgaApiService) DeleteStore(ctx context.Context, storeId string) ApiDeleteStoreRequest { return ApiDeleteStoreRequest{ ApiService: a, ctx: ctx, @@ -1443,22 +1465,13 @@ func (a *OpenFgaApiService) DeleteStore(ctx _context.Context, storeId string) Ap /* * Execute executes the request */ -func (a *OpenFgaApiService) DeleteStoreExecute(r ApiDeleteStoreRequest) (*_nethttp.Response, error) { - var maxRetry int - var minWaitInMs int - var requestStarted time.Time = time.Now() - - if a.RetryParams != nil { - maxRetry = a.RetryParams.MinWaitInMs - minWaitInMs = a.RetryParams.MinWaitInMs - } else { - maxRetry = 0 - minWaitInMs = 0 - } +func (a *OpenFgaApiService) DeleteStoreExecute(r ApiDeleteStoreRequest) (*http.Response, error) { + var requestStarted = time.Now() - for i := 0; i < maxRetry+1; i++ { + retryParams := a.client.cfg.RetryParams + for i := 0; i < retryParams.MaxRetry+1; i++ { var ( - localVarHTTPMethod = _nethttp.MethodDelete + localVarHTTPMethod = http.MethodDelete localVarPostBody interface{} ) @@ -1467,10 +1480,10 @@ func (a *OpenFgaApiService) DeleteStoreExecute(r ApiDeleteStoreRequest) (*_netht return nil, reportError("storeId is required and must be specified") } - localVarPath = strings.Replace(localVarPath, "{"+"store_id"+"}", _neturl.PathEscape(parameterToString(r.storeId, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"store_id"+"}", url.PathEscape(parameterToString(r.storeId, "")), -1) localVarHeaderParams := make(map[string]string) - localVarQueryParams := _neturl.Values{} + localVarQueryParams := url.Values{} // to determine the Content-Type header localVarHTTPContentTypes := []string{} @@ -1496,19 +1509,33 @@ func (a *OpenFgaApiService) DeleteStoreExecute(r ApiDeleteStoreRequest) (*_netht localVarHTTPResponse, err := a.client.callAPI(req) if err != nil || localVarHTTPResponse == nil { + if i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, http.Header{}, "DeleteStore") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } + } return localVarHTTPResponse, err } - localVarBody, err := _ioutil.ReadAll(localVarHTTPResponse.Body) + localVarBody, err := io.ReadAll(localVarHTTPResponse.Body) localVarHTTPResponse.Body.Close() - localVarHTTPResponse.Body = _ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + localVarHTTPResponse.Body = io.NopCloser(bytes.NewBuffer(localVarBody)) if err != nil { + if i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, localVarHTTPResponse.Header, "DeleteStore") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } + } return localVarHTTPResponse, err } - if localVarHTTPResponse.StatusCode >= _nethttp.StatusMultipleChoices { + if localVarHTTPResponse.StatusCode >= http.StatusMultipleChoices { - if localVarHTTPResponse.StatusCode == _nethttp.StatusBadRequest || localVarHTTPResponse.StatusCode == _nethttp.StatusUnprocessableEntity { + if localVarHTTPResponse.StatusCode == http.StatusBadRequest || localVarHTTPResponse.StatusCode == http.StatusUnprocessableEntity { newErr := FgaApiValidationError{ body: localVarBody, storeId: r.storeId, @@ -1534,7 +1561,7 @@ func (a *OpenFgaApiService) DeleteStoreExecute(r ApiDeleteStoreRequest) (*_netht return localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == _nethttp.StatusUnauthorized || localVarHTTPResponse.StatusCode == _nethttp.StatusForbidden { + if localVarHTTPResponse.StatusCode == http.StatusUnauthorized || localVarHTTPResponse.StatusCode == http.StatusForbidden { newErr := FgaApiAuthenticationError{ body: localVarBody, storeId: r.storeId, @@ -1549,7 +1576,7 @@ func (a *OpenFgaApiService) DeleteStoreExecute(r ApiDeleteStoreRequest) (*_netht return localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == _nethttp.StatusNotFound { + if localVarHTTPResponse.StatusCode == http.StatusNotFound { newErr := FgaApiNotFoundError{ body: localVarBody, storeId: r.storeId, @@ -1575,10 +1602,13 @@ func (a *OpenFgaApiService) DeleteStoreExecute(r ApiDeleteStoreRequest) (*_netht return localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == _nethttp.StatusTooManyRequests { - if i < maxRetry { - time.Sleep(time.Duration(internalutils.RandomTime(i, minWaitInMs)) * time.Millisecond) - continue + if localVarHTTPResponse.StatusCode == http.StatusTooManyRequests { + if i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, localVarHTTPResponse.Header, "DeleteStore") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } } // maximum number of retry reached newErr := FgaApiRateLimitExceededError{ @@ -1597,10 +1627,13 @@ func (a *OpenFgaApiService) DeleteStoreExecute(r ApiDeleteStoreRequest) (*_netht return localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode >= _nethttp.StatusInternalServerError { - if localVarHTTPResponse.StatusCode != _nethttp.StatusNotImplemented && i < maxRetry { - time.Sleep(time.Duration(internalutils.RandomTime(i, minWaitInMs)) * time.Millisecond) - continue + if localVarHTTPResponse.StatusCode >= http.StatusInternalServerError { + if localVarHTTPResponse.StatusCode != http.StatusNotImplemented && i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, localVarHTTPResponse.Header, "DeleteStore") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } } newErr := FgaApiInternalError{ body: localVarBody, @@ -1680,7 +1713,7 @@ func (a *OpenFgaApiService) DeleteStoreExecute(r ApiDeleteStoreRequest) (*_netht } type ApiExpandRequest struct { - ctx _context.Context + ctx context.Context ApiService OpenFgaApi storeId string body *ExpandRequest @@ -1691,7 +1724,7 @@ func (r ApiExpandRequest) Body(body ExpandRequest) ApiExpandRequest { return r } -func (r ApiExpandRequest) Execute() (ExpandResponse, *_nethttp.Response, error) { +func (r ApiExpandRequest) Execute() (ExpandResponse, *http.Response, error) { return r.ApiService.ExpandExecute(r) } @@ -1751,11 +1784,11 @@ OpenFGA's response will be a userset tree of the users and usersets that have re ``` The caller can then call expand API for the `writer` relationship for the `document:2021-budget`. - - @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @param storeId - @return ApiExpandRequest */ -func (a *OpenFgaApiService) Expand(ctx _context.Context, storeId string) ApiExpandRequest { +func (a *OpenFgaApiService) Expand(ctx context.Context, storeId string) ApiExpandRequest { return ApiExpandRequest{ ApiService: a, ctx: ctx, @@ -1767,22 +1800,13 @@ func (a *OpenFgaApiService) Expand(ctx _context.Context, storeId string) ApiExpa * Execute executes the request * @return ExpandResponse */ -func (a *OpenFgaApiService) ExpandExecute(r ApiExpandRequest) (ExpandResponse, *_nethttp.Response, error) { - var maxRetry int - var minWaitInMs int - var requestStarted time.Time = time.Now() - - if a.RetryParams != nil { - maxRetry = a.RetryParams.MinWaitInMs - minWaitInMs = a.RetryParams.MinWaitInMs - } else { - maxRetry = 0 - minWaitInMs = 0 - } +func (a *OpenFgaApiService) ExpandExecute(r ApiExpandRequest) (ExpandResponse, *http.Response, error) { + var requestStarted = time.Now() - for i := 0; i < maxRetry+1; i++ { + retryParams := a.client.cfg.RetryParams + for i := 0; i < retryParams.MaxRetry+1; i++ { var ( - localVarHTTPMethod = _nethttp.MethodPost + localVarHTTPMethod = http.MethodPost localVarPostBody interface{} localVarReturnValue ExpandResponse ) @@ -1792,10 +1816,10 @@ func (a *OpenFgaApiService) ExpandExecute(r ApiExpandRequest) (ExpandResponse, * return localVarReturnValue, nil, reportError("storeId is required and must be specified") } - localVarPath = strings.Replace(localVarPath, "{"+"store_id"+"}", _neturl.PathEscape(parameterToString(r.storeId, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"store_id"+"}", url.PathEscape(parameterToString(r.storeId, "")), -1) localVarHeaderParams := make(map[string]string) - localVarQueryParams := _neturl.Values{} + localVarQueryParams := url.Values{} if r.body == nil { return localVarReturnValue, nil, reportError("body is required and must be specified") } @@ -1826,19 +1850,33 @@ func (a *OpenFgaApiService) ExpandExecute(r ApiExpandRequest) (ExpandResponse, * localVarHTTPResponse, err := a.client.callAPI(req) if err != nil || localVarHTTPResponse == nil { + if i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, http.Header{}, "Expand") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } + } return localVarReturnValue, localVarHTTPResponse, err } - localVarBody, err := _ioutil.ReadAll(localVarHTTPResponse.Body) + localVarBody, err := io.ReadAll(localVarHTTPResponse.Body) localVarHTTPResponse.Body.Close() - localVarHTTPResponse.Body = _ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + localVarHTTPResponse.Body = io.NopCloser(bytes.NewBuffer(localVarBody)) if err != nil { + if i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, localVarHTTPResponse.Header, "Expand") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } + } return localVarReturnValue, localVarHTTPResponse, err } - if localVarHTTPResponse.StatusCode >= _nethttp.StatusMultipleChoices { + if localVarHTTPResponse.StatusCode >= http.StatusMultipleChoices { - if localVarHTTPResponse.StatusCode == _nethttp.StatusBadRequest || localVarHTTPResponse.StatusCode == _nethttp.StatusUnprocessableEntity { + if localVarHTTPResponse.StatusCode == http.StatusBadRequest || localVarHTTPResponse.StatusCode == http.StatusUnprocessableEntity { newErr := FgaApiValidationError{ body: localVarBody, storeId: r.storeId, @@ -1864,7 +1902,7 @@ func (a *OpenFgaApiService) ExpandExecute(r ApiExpandRequest) (ExpandResponse, * return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == _nethttp.StatusUnauthorized || localVarHTTPResponse.StatusCode == _nethttp.StatusForbidden { + if localVarHTTPResponse.StatusCode == http.StatusUnauthorized || localVarHTTPResponse.StatusCode == http.StatusForbidden { newErr := FgaApiAuthenticationError{ body: localVarBody, storeId: r.storeId, @@ -1879,7 +1917,7 @@ func (a *OpenFgaApiService) ExpandExecute(r ApiExpandRequest) (ExpandResponse, * return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == _nethttp.StatusNotFound { + if localVarHTTPResponse.StatusCode == http.StatusNotFound { newErr := FgaApiNotFoundError{ body: localVarBody, storeId: r.storeId, @@ -1905,10 +1943,13 @@ func (a *OpenFgaApiService) ExpandExecute(r ApiExpandRequest) (ExpandResponse, * return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == _nethttp.StatusTooManyRequests { - if i < maxRetry { - time.Sleep(time.Duration(internalutils.RandomTime(i, minWaitInMs)) * time.Millisecond) - continue + if localVarHTTPResponse.StatusCode == http.StatusTooManyRequests { + if i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, localVarHTTPResponse.Header, "Expand") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } } // maximum number of retry reached newErr := FgaApiRateLimitExceededError{ @@ -1927,10 +1968,13 @@ func (a *OpenFgaApiService) ExpandExecute(r ApiExpandRequest) (ExpandResponse, * return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode >= _nethttp.StatusInternalServerError { - if localVarHTTPResponse.StatusCode != _nethttp.StatusNotImplemented && i < maxRetry { - time.Sleep(time.Duration(internalutils.RandomTime(i, minWaitInMs)) * time.Millisecond) - continue + if localVarHTTPResponse.StatusCode >= http.StatusInternalServerError { + if localVarHTTPResponse.StatusCode != http.StatusNotImplemented && i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, localVarHTTPResponse.Header, "Expand") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } } newErr := FgaApiInternalError{ body: localVarBody, @@ -2020,23 +2064,23 @@ func (a *OpenFgaApiService) ExpandExecute(r ApiExpandRequest) (ExpandResponse, * } type ApiGetStoreRequest struct { - ctx _context.Context + ctx context.Context ApiService OpenFgaApi storeId string } -func (r ApiGetStoreRequest) Execute() (GetStoreResponse, *_nethttp.Response, error) { +func (r ApiGetStoreRequest) Execute() (GetStoreResponse, *http.Response, error) { return r.ApiService.GetStoreExecute(r) } /* * GetStore Get a store * Returns an OpenFGA store by its identifier - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). * @param storeId * @return ApiGetStoreRequest */ -func (a *OpenFgaApiService) GetStore(ctx _context.Context, storeId string) ApiGetStoreRequest { +func (a *OpenFgaApiService) GetStore(ctx context.Context, storeId string) ApiGetStoreRequest { return ApiGetStoreRequest{ ApiService: a, ctx: ctx, @@ -2048,22 +2092,13 @@ func (a *OpenFgaApiService) GetStore(ctx _context.Context, storeId string) ApiGe * Execute executes the request * @return GetStoreResponse */ -func (a *OpenFgaApiService) GetStoreExecute(r ApiGetStoreRequest) (GetStoreResponse, *_nethttp.Response, error) { - var maxRetry int - var minWaitInMs int - var requestStarted time.Time = time.Now() - - if a.RetryParams != nil { - maxRetry = a.RetryParams.MinWaitInMs - minWaitInMs = a.RetryParams.MinWaitInMs - } else { - maxRetry = 0 - minWaitInMs = 0 - } +func (a *OpenFgaApiService) GetStoreExecute(r ApiGetStoreRequest) (GetStoreResponse, *http.Response, error) { + var requestStarted = time.Now() - for i := 0; i < maxRetry+1; i++ { + retryParams := a.client.cfg.RetryParams + for i := 0; i < retryParams.MaxRetry+1; i++ { var ( - localVarHTTPMethod = _nethttp.MethodGet + localVarHTTPMethod = http.MethodGet localVarPostBody interface{} localVarReturnValue GetStoreResponse ) @@ -2073,10 +2108,10 @@ func (a *OpenFgaApiService) GetStoreExecute(r ApiGetStoreRequest) (GetStoreRespo return localVarReturnValue, nil, reportError("storeId is required and must be specified") } - localVarPath = strings.Replace(localVarPath, "{"+"store_id"+"}", _neturl.PathEscape(parameterToString(r.storeId, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"store_id"+"}", url.PathEscape(parameterToString(r.storeId, "")), -1) localVarHeaderParams := make(map[string]string) - localVarQueryParams := _neturl.Values{} + localVarQueryParams := url.Values{} // to determine the Content-Type header localVarHTTPContentTypes := []string{} @@ -2102,19 +2137,33 @@ func (a *OpenFgaApiService) GetStoreExecute(r ApiGetStoreRequest) (GetStoreRespo localVarHTTPResponse, err := a.client.callAPI(req) if err != nil || localVarHTTPResponse == nil { + if i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, http.Header{}, "GetStore") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } + } return localVarReturnValue, localVarHTTPResponse, err } - localVarBody, err := _ioutil.ReadAll(localVarHTTPResponse.Body) + localVarBody, err := io.ReadAll(localVarHTTPResponse.Body) localVarHTTPResponse.Body.Close() - localVarHTTPResponse.Body = _ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + localVarHTTPResponse.Body = io.NopCloser(bytes.NewBuffer(localVarBody)) if err != nil { + if i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, localVarHTTPResponse.Header, "GetStore") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } + } return localVarReturnValue, localVarHTTPResponse, err } - if localVarHTTPResponse.StatusCode >= _nethttp.StatusMultipleChoices { + if localVarHTTPResponse.StatusCode >= http.StatusMultipleChoices { - if localVarHTTPResponse.StatusCode == _nethttp.StatusBadRequest || localVarHTTPResponse.StatusCode == _nethttp.StatusUnprocessableEntity { + if localVarHTTPResponse.StatusCode == http.StatusBadRequest || localVarHTTPResponse.StatusCode == http.StatusUnprocessableEntity { newErr := FgaApiValidationError{ body: localVarBody, storeId: r.storeId, @@ -2140,7 +2189,7 @@ func (a *OpenFgaApiService) GetStoreExecute(r ApiGetStoreRequest) (GetStoreRespo return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == _nethttp.StatusUnauthorized || localVarHTTPResponse.StatusCode == _nethttp.StatusForbidden { + if localVarHTTPResponse.StatusCode == http.StatusUnauthorized || localVarHTTPResponse.StatusCode == http.StatusForbidden { newErr := FgaApiAuthenticationError{ body: localVarBody, storeId: r.storeId, @@ -2155,7 +2204,7 @@ func (a *OpenFgaApiService) GetStoreExecute(r ApiGetStoreRequest) (GetStoreRespo return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == _nethttp.StatusNotFound { + if localVarHTTPResponse.StatusCode == http.StatusNotFound { newErr := FgaApiNotFoundError{ body: localVarBody, storeId: r.storeId, @@ -2181,10 +2230,13 @@ func (a *OpenFgaApiService) GetStoreExecute(r ApiGetStoreRequest) (GetStoreRespo return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == _nethttp.StatusTooManyRequests { - if i < maxRetry { - time.Sleep(time.Duration(internalutils.RandomTime(i, minWaitInMs)) * time.Millisecond) - continue + if localVarHTTPResponse.StatusCode == http.StatusTooManyRequests { + if i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, localVarHTTPResponse.Header, "GetStore") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } } // maximum number of retry reached newErr := FgaApiRateLimitExceededError{ @@ -2203,10 +2255,13 @@ func (a *OpenFgaApiService) GetStoreExecute(r ApiGetStoreRequest) (GetStoreRespo return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode >= _nethttp.StatusInternalServerError { - if localVarHTTPResponse.StatusCode != _nethttp.StatusNotImplemented && i < maxRetry { - time.Sleep(time.Duration(internalutils.RandomTime(i, minWaitInMs)) * time.Millisecond) - continue + if localVarHTTPResponse.StatusCode >= http.StatusInternalServerError { + if localVarHTTPResponse.StatusCode != http.StatusNotImplemented && i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, localVarHTTPResponse.Header, "GetStore") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } } newErr := FgaApiInternalError{ body: localVarBody, @@ -2296,7 +2351,7 @@ func (a *OpenFgaApiService) GetStoreExecute(r ApiGetStoreRequest) (GetStoreRespo } type ApiListObjectsRequest struct { - ctx _context.Context + ctx context.Context ApiService OpenFgaApi storeId string body *ListObjectsRequest @@ -2307,7 +2362,7 @@ func (r ApiListObjectsRequest) Body(body ListObjectsRequest) ApiListObjectsReque return r } -func (r ApiListObjectsRequest) Execute() (ListObjectsResponse, *_nethttp.Response, error) { +func (r ApiListObjectsRequest) Execute() (ListObjectsResponse, *http.Response, error) { return r.ApiService.ListObjectsExecute(r) } @@ -2323,11 +2378,11 @@ By default, the Check API caches results for a short time to optimize performanc The response will contain the related objects in an array in the "objects" field of the response and they will be strings in the object format `:` (e.g. "document:roadmap"). The number of objects in the response array will be limited by the execution timeout specified in the flag OPENFGA_LIST_OBJECTS_DEADLINE and by the upper bound specified in the flag OPENFGA_LIST_OBJECTS_MAX_RESULTS, whichever is hit first. The objects given will not be sorted, and therefore two identical calls can give a given different set of objects. - - @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @param storeId - @return ApiListObjectsRequest */ -func (a *OpenFgaApiService) ListObjects(ctx _context.Context, storeId string) ApiListObjectsRequest { +func (a *OpenFgaApiService) ListObjects(ctx context.Context, storeId string) ApiListObjectsRequest { return ApiListObjectsRequest{ ApiService: a, ctx: ctx, @@ -2339,22 +2394,13 @@ func (a *OpenFgaApiService) ListObjects(ctx _context.Context, storeId string) Ap * Execute executes the request * @return ListObjectsResponse */ -func (a *OpenFgaApiService) ListObjectsExecute(r ApiListObjectsRequest) (ListObjectsResponse, *_nethttp.Response, error) { - var maxRetry int - var minWaitInMs int - var requestStarted time.Time = time.Now() - - if a.RetryParams != nil { - maxRetry = a.RetryParams.MinWaitInMs - minWaitInMs = a.RetryParams.MinWaitInMs - } else { - maxRetry = 0 - minWaitInMs = 0 - } +func (a *OpenFgaApiService) ListObjectsExecute(r ApiListObjectsRequest) (ListObjectsResponse, *http.Response, error) { + var requestStarted = time.Now() - for i := 0; i < maxRetry+1; i++ { + retryParams := a.client.cfg.RetryParams + for i := 0; i < retryParams.MaxRetry+1; i++ { var ( - localVarHTTPMethod = _nethttp.MethodPost + localVarHTTPMethod = http.MethodPost localVarPostBody interface{} localVarReturnValue ListObjectsResponse ) @@ -2364,10 +2410,10 @@ func (a *OpenFgaApiService) ListObjectsExecute(r ApiListObjectsRequest) (ListObj return localVarReturnValue, nil, reportError("storeId is required and must be specified") } - localVarPath = strings.Replace(localVarPath, "{"+"store_id"+"}", _neturl.PathEscape(parameterToString(r.storeId, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"store_id"+"}", url.PathEscape(parameterToString(r.storeId, "")), -1) localVarHeaderParams := make(map[string]string) - localVarQueryParams := _neturl.Values{} + localVarQueryParams := url.Values{} if r.body == nil { return localVarReturnValue, nil, reportError("body is required and must be specified") } @@ -2398,19 +2444,33 @@ func (a *OpenFgaApiService) ListObjectsExecute(r ApiListObjectsRequest) (ListObj localVarHTTPResponse, err := a.client.callAPI(req) if err != nil || localVarHTTPResponse == nil { + if i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, http.Header{}, "ListObjects") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } + } return localVarReturnValue, localVarHTTPResponse, err } - localVarBody, err := _ioutil.ReadAll(localVarHTTPResponse.Body) + localVarBody, err := io.ReadAll(localVarHTTPResponse.Body) localVarHTTPResponse.Body.Close() - localVarHTTPResponse.Body = _ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + localVarHTTPResponse.Body = io.NopCloser(bytes.NewBuffer(localVarBody)) if err != nil { + if i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, localVarHTTPResponse.Header, "ListObjects") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } + } return localVarReturnValue, localVarHTTPResponse, err } - if localVarHTTPResponse.StatusCode >= _nethttp.StatusMultipleChoices { + if localVarHTTPResponse.StatusCode >= http.StatusMultipleChoices { - if localVarHTTPResponse.StatusCode == _nethttp.StatusBadRequest || localVarHTTPResponse.StatusCode == _nethttp.StatusUnprocessableEntity { + if localVarHTTPResponse.StatusCode == http.StatusBadRequest || localVarHTTPResponse.StatusCode == http.StatusUnprocessableEntity { newErr := FgaApiValidationError{ body: localVarBody, storeId: r.storeId, @@ -2436,7 +2496,7 @@ func (a *OpenFgaApiService) ListObjectsExecute(r ApiListObjectsRequest) (ListObj return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == _nethttp.StatusUnauthorized || localVarHTTPResponse.StatusCode == _nethttp.StatusForbidden { + if localVarHTTPResponse.StatusCode == http.StatusUnauthorized || localVarHTTPResponse.StatusCode == http.StatusForbidden { newErr := FgaApiAuthenticationError{ body: localVarBody, storeId: r.storeId, @@ -2451,7 +2511,7 @@ func (a *OpenFgaApiService) ListObjectsExecute(r ApiListObjectsRequest) (ListObj return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == _nethttp.StatusNotFound { + if localVarHTTPResponse.StatusCode == http.StatusNotFound { newErr := FgaApiNotFoundError{ body: localVarBody, storeId: r.storeId, @@ -2477,10 +2537,13 @@ func (a *OpenFgaApiService) ListObjectsExecute(r ApiListObjectsRequest) (ListObj return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == _nethttp.StatusTooManyRequests { - if i < maxRetry { - time.Sleep(time.Duration(internalutils.RandomTime(i, minWaitInMs)) * time.Millisecond) - continue + if localVarHTTPResponse.StatusCode == http.StatusTooManyRequests { + if i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, localVarHTTPResponse.Header, "ListObjects") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } } // maximum number of retry reached newErr := FgaApiRateLimitExceededError{ @@ -2499,10 +2562,13 @@ func (a *OpenFgaApiService) ListObjectsExecute(r ApiListObjectsRequest) (ListObj return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode >= _nethttp.StatusInternalServerError { - if localVarHTTPResponse.StatusCode != _nethttp.StatusNotImplemented && i < maxRetry { - time.Sleep(time.Duration(internalutils.RandomTime(i, minWaitInMs)) * time.Millisecond) - continue + if localVarHTTPResponse.StatusCode >= http.StatusInternalServerError { + if localVarHTTPResponse.StatusCode != http.StatusNotImplemented && i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, localVarHTTPResponse.Header, "ListObjects") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } } newErr := FgaApiInternalError{ body: localVarBody, @@ -2592,7 +2658,7 @@ func (a *OpenFgaApiService) ListObjectsExecute(r ApiListObjectsRequest) (ListObj } type ApiListStoresRequest struct { - ctx _context.Context + ctx context.Context ApiService OpenFgaApi pageSize *int32 continuationToken *string @@ -2607,7 +2673,7 @@ func (r ApiListStoresRequest) ContinuationToken(continuationToken string) ApiLis return r } -func (r ApiListStoresRequest) Execute() (ListStoresResponse, *_nethttp.Response, error) { +func (r ApiListStoresRequest) Execute() (ListStoresResponse, *http.Response, error) { return r.ApiService.ListStoresExecute(r) } @@ -2617,10 +2683,10 @@ func (r ApiListStoresRequest) Execute() (ListStoresResponse, *_nethttp.Response, The continuation token will be empty if there are no more stores. - - @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @return ApiListStoresRequest */ -func (a *OpenFgaApiService) ListStores(ctx _context.Context) ApiListStoresRequest { +func (a *OpenFgaApiService) ListStores(ctx context.Context) ApiListStoresRequest { return ApiListStoresRequest{ ApiService: a, ctx: ctx, @@ -2631,22 +2697,13 @@ func (a *OpenFgaApiService) ListStores(ctx _context.Context) ApiListStoresReques * Execute executes the request * @return ListStoresResponse */ -func (a *OpenFgaApiService) ListStoresExecute(r ApiListStoresRequest) (ListStoresResponse, *_nethttp.Response, error) { - var maxRetry int - var minWaitInMs int - var requestStarted time.Time = time.Now() - - if a.RetryParams != nil { - maxRetry = a.RetryParams.MinWaitInMs - minWaitInMs = a.RetryParams.MinWaitInMs - } else { - maxRetry = 0 - minWaitInMs = 0 - } +func (a *OpenFgaApiService) ListStoresExecute(r ApiListStoresRequest) (ListStoresResponse, *http.Response, error) { + var requestStarted = time.Now() - for i := 0; i < maxRetry+1; i++ { + retryParams := a.client.cfg.RetryParams + for i := 0; i < retryParams.MaxRetry+1; i++ { var ( - localVarHTTPMethod = _nethttp.MethodGet + localVarHTTPMethod = http.MethodGet localVarPostBody interface{} localVarReturnValue ListStoresResponse ) @@ -2654,7 +2711,7 @@ func (a *OpenFgaApiService) ListStoresExecute(r ApiListStoresRequest) (ListStore localVarPath := "/stores" localVarHeaderParams := make(map[string]string) - localVarQueryParams := _neturl.Values{} + localVarQueryParams := url.Values{} if r.pageSize != nil { localVarQueryParams.Add("page_size", parameterToString(*r.pageSize, "")) @@ -2686,19 +2743,33 @@ func (a *OpenFgaApiService) ListStoresExecute(r ApiListStoresRequest) (ListStore localVarHTTPResponse, err := a.client.callAPI(req) if err != nil || localVarHTTPResponse == nil { + if i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, http.Header{}, "ListStores") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } + } return localVarReturnValue, localVarHTTPResponse, err } - localVarBody, err := _ioutil.ReadAll(localVarHTTPResponse.Body) + localVarBody, err := io.ReadAll(localVarHTTPResponse.Body) localVarHTTPResponse.Body.Close() - localVarHTTPResponse.Body = _ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + localVarHTTPResponse.Body = io.NopCloser(bytes.NewBuffer(localVarBody)) if err != nil { + if i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, localVarHTTPResponse.Header, "ListStores") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } + } return localVarReturnValue, localVarHTTPResponse, err } - if localVarHTTPResponse.StatusCode >= _nethttp.StatusMultipleChoices { + if localVarHTTPResponse.StatusCode >= http.StatusMultipleChoices { - if localVarHTTPResponse.StatusCode == _nethttp.StatusBadRequest || localVarHTTPResponse.StatusCode == _nethttp.StatusUnprocessableEntity { + if localVarHTTPResponse.StatusCode == http.StatusBadRequest || localVarHTTPResponse.StatusCode == http.StatusUnprocessableEntity { newErr := FgaApiValidationError{ body: localVarBody, endpointCategory: "ListStores", @@ -2723,7 +2794,7 @@ func (a *OpenFgaApiService) ListStoresExecute(r ApiListStoresRequest) (ListStore return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == _nethttp.StatusUnauthorized || localVarHTTPResponse.StatusCode == _nethttp.StatusForbidden { + if localVarHTTPResponse.StatusCode == http.StatusUnauthorized || localVarHTTPResponse.StatusCode == http.StatusForbidden { newErr := FgaApiAuthenticationError{ body: localVarBody, endpointCategory: "ListStores", @@ -2737,7 +2808,7 @@ func (a *OpenFgaApiService) ListStoresExecute(r ApiListStoresRequest) (ListStore return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == _nethttp.StatusNotFound { + if localVarHTTPResponse.StatusCode == http.StatusNotFound { newErr := FgaApiNotFoundError{ body: localVarBody, endpointCategory: "ListStores", @@ -2762,10 +2833,13 @@ func (a *OpenFgaApiService) ListStoresExecute(r ApiListStoresRequest) (ListStore return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == _nethttp.StatusTooManyRequests { - if i < maxRetry { - time.Sleep(time.Duration(internalutils.RandomTime(i, minWaitInMs)) * time.Millisecond) - continue + if localVarHTTPResponse.StatusCode == http.StatusTooManyRequests { + if i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, localVarHTTPResponse.Header, "ListStores") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } } // maximum number of retry reached newErr := FgaApiRateLimitExceededError{ @@ -2783,10 +2857,13 @@ func (a *OpenFgaApiService) ListStoresExecute(r ApiListStoresRequest) (ListStore return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode >= _nethttp.StatusInternalServerError { - if localVarHTTPResponse.StatusCode != _nethttp.StatusNotImplemented && i < maxRetry { - time.Sleep(time.Duration(internalutils.RandomTime(i, minWaitInMs)) * time.Millisecond) - continue + if localVarHTTPResponse.StatusCode >= http.StatusInternalServerError { + if localVarHTTPResponse.StatusCode != http.StatusNotImplemented && i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, localVarHTTPResponse.Header, "ListStores") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } } newErr := FgaApiInternalError{ body: localVarBody, @@ -2873,7 +2950,7 @@ func (a *OpenFgaApiService) ListStoresExecute(r ApiListStoresRequest) (ListStore } type ApiListUsersRequest struct { - ctx _context.Context + ctx context.Context ApiService OpenFgaApi storeId string body *ListUsersRequest @@ -2884,7 +2961,7 @@ func (r ApiListUsersRequest) Body(body ListUsersRequest) ApiListUsersRequest { return r } -func (r ApiListUsersRequest) Execute() (ListUsersResponse, *_nethttp.Response, error) { +func (r ApiListUsersRequest) Execute() (ListUsersResponse, *http.Response, error) { return r.ApiService.ListUsersExecute(r) } @@ -2901,11 +2978,11 @@ or type-bound public access. Each of these types of results is encoded in its ow of that type have a relation to the object; it is possible that negations exist and checks should still be queried on individual subjects to ensure access to that document.The number of users in the response array will be limited by the execution timeout specified in the flag OPENFGA_LIST_USERS_DEADLINE and by the upper bound specified in the flag OPENFGA_LIST_USERS_MAX_RESULTS, whichever is hit first. The returned users will not be sorted, and therefore two identical calls may yield different sets of users. - - @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @param storeId - @return ApiListUsersRequest */ -func (a *OpenFgaApiService) ListUsers(ctx _context.Context, storeId string) ApiListUsersRequest { +func (a *OpenFgaApiService) ListUsers(ctx context.Context, storeId string) ApiListUsersRequest { return ApiListUsersRequest{ ApiService: a, ctx: ctx, @@ -2917,22 +2994,13 @@ func (a *OpenFgaApiService) ListUsers(ctx _context.Context, storeId string) ApiL * Execute executes the request * @return ListUsersResponse */ -func (a *OpenFgaApiService) ListUsersExecute(r ApiListUsersRequest) (ListUsersResponse, *_nethttp.Response, error) { - var maxRetry int - var minWaitInMs int - var requestStarted time.Time = time.Now() - - if a.RetryParams != nil { - maxRetry = a.RetryParams.MinWaitInMs - minWaitInMs = a.RetryParams.MinWaitInMs - } else { - maxRetry = 0 - minWaitInMs = 0 - } +func (a *OpenFgaApiService) ListUsersExecute(r ApiListUsersRequest) (ListUsersResponse, *http.Response, error) { + var requestStarted = time.Now() - for i := 0; i < maxRetry+1; i++ { + retryParams := a.client.cfg.RetryParams + for i := 0; i < retryParams.MaxRetry+1; i++ { var ( - localVarHTTPMethod = _nethttp.MethodPost + localVarHTTPMethod = http.MethodPost localVarPostBody interface{} localVarReturnValue ListUsersResponse ) @@ -2942,10 +3010,10 @@ func (a *OpenFgaApiService) ListUsersExecute(r ApiListUsersRequest) (ListUsersRe return localVarReturnValue, nil, reportError("storeId is required and must be specified") } - localVarPath = strings.Replace(localVarPath, "{"+"store_id"+"}", _neturl.PathEscape(parameterToString(r.storeId, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"store_id"+"}", url.PathEscape(parameterToString(r.storeId, "")), -1) localVarHeaderParams := make(map[string]string) - localVarQueryParams := _neturl.Values{} + localVarQueryParams := url.Values{} if r.body == nil { return localVarReturnValue, nil, reportError("body is required and must be specified") } @@ -2976,19 +3044,33 @@ func (a *OpenFgaApiService) ListUsersExecute(r ApiListUsersRequest) (ListUsersRe localVarHTTPResponse, err := a.client.callAPI(req) if err != nil || localVarHTTPResponse == nil { + if i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, http.Header{}, "ListUsers") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } + } return localVarReturnValue, localVarHTTPResponse, err } - localVarBody, err := _ioutil.ReadAll(localVarHTTPResponse.Body) + localVarBody, err := io.ReadAll(localVarHTTPResponse.Body) localVarHTTPResponse.Body.Close() - localVarHTTPResponse.Body = _ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + localVarHTTPResponse.Body = io.NopCloser(bytes.NewBuffer(localVarBody)) if err != nil { + if i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, localVarHTTPResponse.Header, "ListUsers") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } + } return localVarReturnValue, localVarHTTPResponse, err } - if localVarHTTPResponse.StatusCode >= _nethttp.StatusMultipleChoices { + if localVarHTTPResponse.StatusCode >= http.StatusMultipleChoices { - if localVarHTTPResponse.StatusCode == _nethttp.StatusBadRequest || localVarHTTPResponse.StatusCode == _nethttp.StatusUnprocessableEntity { + if localVarHTTPResponse.StatusCode == http.StatusBadRequest || localVarHTTPResponse.StatusCode == http.StatusUnprocessableEntity { newErr := FgaApiValidationError{ body: localVarBody, storeId: r.storeId, @@ -3014,7 +3096,7 @@ func (a *OpenFgaApiService) ListUsersExecute(r ApiListUsersRequest) (ListUsersRe return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == _nethttp.StatusUnauthorized || localVarHTTPResponse.StatusCode == _nethttp.StatusForbidden { + if localVarHTTPResponse.StatusCode == http.StatusUnauthorized || localVarHTTPResponse.StatusCode == http.StatusForbidden { newErr := FgaApiAuthenticationError{ body: localVarBody, storeId: r.storeId, @@ -3029,7 +3111,7 @@ func (a *OpenFgaApiService) ListUsersExecute(r ApiListUsersRequest) (ListUsersRe return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == _nethttp.StatusNotFound { + if localVarHTTPResponse.StatusCode == http.StatusNotFound { newErr := FgaApiNotFoundError{ body: localVarBody, storeId: r.storeId, @@ -3055,10 +3137,13 @@ func (a *OpenFgaApiService) ListUsersExecute(r ApiListUsersRequest) (ListUsersRe return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == _nethttp.StatusTooManyRequests { - if i < maxRetry { - time.Sleep(time.Duration(internalutils.RandomTime(i, minWaitInMs)) * time.Millisecond) - continue + if localVarHTTPResponse.StatusCode == http.StatusTooManyRequests { + if i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, localVarHTTPResponse.Header, "ListUsers") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } } // maximum number of retry reached newErr := FgaApiRateLimitExceededError{ @@ -3077,10 +3162,13 @@ func (a *OpenFgaApiService) ListUsersExecute(r ApiListUsersRequest) (ListUsersRe return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode >= _nethttp.StatusInternalServerError { - if localVarHTTPResponse.StatusCode != _nethttp.StatusNotImplemented && i < maxRetry { - time.Sleep(time.Duration(internalutils.RandomTime(i, minWaitInMs)) * time.Millisecond) - continue + if localVarHTTPResponse.StatusCode >= http.StatusInternalServerError { + if localVarHTTPResponse.StatusCode != http.StatusNotImplemented && i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, localVarHTTPResponse.Header, "ListUsers") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } } newErr := FgaApiInternalError{ body: localVarBody, @@ -3170,7 +3258,7 @@ func (a *OpenFgaApiService) ListUsersExecute(r ApiListUsersRequest) (ListUsersRe } type ApiReadRequest struct { - ctx _context.Context + ctx context.Context ApiService OpenFgaApi storeId string body *ReadRequest @@ -3181,7 +3269,7 @@ func (r ApiReadRequest) Body(body ReadRequest) ApiReadRequest { return r } -func (r ApiReadRequest) Execute() (ReadResponse, *_nethttp.Response, error) { +func (r ApiReadRequest) Execute() (ReadResponse, *http.Response, error) { return r.ApiService.ReadExecute(r) } @@ -3299,11 +3387,11 @@ The API will return something like ``` This means that `document:2021-budget` has 1 `reader` (`user:bob`) and 1 `writer` (`user:anne`). - - @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @param storeId - @return ApiReadRequest */ -func (a *OpenFgaApiService) Read(ctx _context.Context, storeId string) ApiReadRequest { +func (a *OpenFgaApiService) Read(ctx context.Context, storeId string) ApiReadRequest { return ApiReadRequest{ ApiService: a, ctx: ctx, @@ -3315,22 +3403,13 @@ func (a *OpenFgaApiService) Read(ctx _context.Context, storeId string) ApiReadRe * Execute executes the request * @return ReadResponse */ -func (a *OpenFgaApiService) ReadExecute(r ApiReadRequest) (ReadResponse, *_nethttp.Response, error) { - var maxRetry int - var minWaitInMs int - var requestStarted time.Time = time.Now() - - if a.RetryParams != nil { - maxRetry = a.RetryParams.MinWaitInMs - minWaitInMs = a.RetryParams.MinWaitInMs - } else { - maxRetry = 0 - minWaitInMs = 0 - } +func (a *OpenFgaApiService) ReadExecute(r ApiReadRequest) (ReadResponse, *http.Response, error) { + var requestStarted = time.Now() - for i := 0; i < maxRetry+1; i++ { + retryParams := a.client.cfg.RetryParams + for i := 0; i < retryParams.MaxRetry+1; i++ { var ( - localVarHTTPMethod = _nethttp.MethodPost + localVarHTTPMethod = http.MethodPost localVarPostBody interface{} localVarReturnValue ReadResponse ) @@ -3340,10 +3419,10 @@ func (a *OpenFgaApiService) ReadExecute(r ApiReadRequest) (ReadResponse, *_netht return localVarReturnValue, nil, reportError("storeId is required and must be specified") } - localVarPath = strings.Replace(localVarPath, "{"+"store_id"+"}", _neturl.PathEscape(parameterToString(r.storeId, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"store_id"+"}", url.PathEscape(parameterToString(r.storeId, "")), -1) localVarHeaderParams := make(map[string]string) - localVarQueryParams := _neturl.Values{} + localVarQueryParams := url.Values{} if r.body == nil { return localVarReturnValue, nil, reportError("body is required and must be specified") } @@ -3374,19 +3453,33 @@ func (a *OpenFgaApiService) ReadExecute(r ApiReadRequest) (ReadResponse, *_netht localVarHTTPResponse, err := a.client.callAPI(req) if err != nil || localVarHTTPResponse == nil { + if i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, http.Header{}, "Read") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } + } return localVarReturnValue, localVarHTTPResponse, err } - localVarBody, err := _ioutil.ReadAll(localVarHTTPResponse.Body) + localVarBody, err := io.ReadAll(localVarHTTPResponse.Body) localVarHTTPResponse.Body.Close() - localVarHTTPResponse.Body = _ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + localVarHTTPResponse.Body = io.NopCloser(bytes.NewBuffer(localVarBody)) if err != nil { + if i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, localVarHTTPResponse.Header, "Read") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } + } return localVarReturnValue, localVarHTTPResponse, err } - if localVarHTTPResponse.StatusCode >= _nethttp.StatusMultipleChoices { + if localVarHTTPResponse.StatusCode >= http.StatusMultipleChoices { - if localVarHTTPResponse.StatusCode == _nethttp.StatusBadRequest || localVarHTTPResponse.StatusCode == _nethttp.StatusUnprocessableEntity { + if localVarHTTPResponse.StatusCode == http.StatusBadRequest || localVarHTTPResponse.StatusCode == http.StatusUnprocessableEntity { newErr := FgaApiValidationError{ body: localVarBody, storeId: r.storeId, @@ -3412,7 +3505,7 @@ func (a *OpenFgaApiService) ReadExecute(r ApiReadRequest) (ReadResponse, *_netht return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == _nethttp.StatusUnauthorized || localVarHTTPResponse.StatusCode == _nethttp.StatusForbidden { + if localVarHTTPResponse.StatusCode == http.StatusUnauthorized || localVarHTTPResponse.StatusCode == http.StatusForbidden { newErr := FgaApiAuthenticationError{ body: localVarBody, storeId: r.storeId, @@ -3427,7 +3520,7 @@ func (a *OpenFgaApiService) ReadExecute(r ApiReadRequest) (ReadResponse, *_netht return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == _nethttp.StatusNotFound { + if localVarHTTPResponse.StatusCode == http.StatusNotFound { newErr := FgaApiNotFoundError{ body: localVarBody, storeId: r.storeId, @@ -3453,10 +3546,13 @@ func (a *OpenFgaApiService) ReadExecute(r ApiReadRequest) (ReadResponse, *_netht return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == _nethttp.StatusTooManyRequests { - if i < maxRetry { - time.Sleep(time.Duration(internalutils.RandomTime(i, minWaitInMs)) * time.Millisecond) - continue + if localVarHTTPResponse.StatusCode == http.StatusTooManyRequests { + if i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, localVarHTTPResponse.Header, "Read") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } } // maximum number of retry reached newErr := FgaApiRateLimitExceededError{ @@ -3475,10 +3571,13 @@ func (a *OpenFgaApiService) ReadExecute(r ApiReadRequest) (ReadResponse, *_netht return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode >= _nethttp.StatusInternalServerError { - if localVarHTTPResponse.StatusCode != _nethttp.StatusNotImplemented && i < maxRetry { - time.Sleep(time.Duration(internalutils.RandomTime(i, minWaitInMs)) * time.Millisecond) - continue + if localVarHTTPResponse.StatusCode >= http.StatusInternalServerError { + if localVarHTTPResponse.StatusCode != http.StatusNotImplemented && i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, localVarHTTPResponse.Header, "Read") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } } newErr := FgaApiInternalError{ body: localVarBody, @@ -3568,25 +3667,25 @@ func (a *OpenFgaApiService) ReadExecute(r ApiReadRequest) (ReadResponse, *_netht } type ApiReadAssertionsRequest struct { - ctx _context.Context + ctx context.Context ApiService OpenFgaApi storeId string authorizationModelId string } -func (r ApiReadAssertionsRequest) Execute() (ReadAssertionsResponse, *_nethttp.Response, error) { +func (r ApiReadAssertionsRequest) Execute() (ReadAssertionsResponse, *http.Response, error) { return r.ApiService.ReadAssertionsExecute(r) } /* * ReadAssertions Read assertions for an authorization model ID * The ReadAssertions API will return, for a given authorization model id, all the assertions stored for it. - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). * @param storeId * @param authorizationModelId * @return ApiReadAssertionsRequest */ -func (a *OpenFgaApiService) ReadAssertions(ctx _context.Context, storeId string, authorizationModelId string) ApiReadAssertionsRequest { +func (a *OpenFgaApiService) ReadAssertions(ctx context.Context, storeId string, authorizationModelId string) ApiReadAssertionsRequest { return ApiReadAssertionsRequest{ ApiService: a, ctx: ctx, @@ -3599,22 +3698,13 @@ func (a *OpenFgaApiService) ReadAssertions(ctx _context.Context, storeId string, * Execute executes the request * @return ReadAssertionsResponse */ -func (a *OpenFgaApiService) ReadAssertionsExecute(r ApiReadAssertionsRequest) (ReadAssertionsResponse, *_nethttp.Response, error) { - var maxRetry int - var minWaitInMs int - var requestStarted time.Time = time.Now() - - if a.RetryParams != nil { - maxRetry = a.RetryParams.MinWaitInMs - minWaitInMs = a.RetryParams.MinWaitInMs - } else { - maxRetry = 0 - minWaitInMs = 0 - } +func (a *OpenFgaApiService) ReadAssertionsExecute(r ApiReadAssertionsRequest) (ReadAssertionsResponse, *http.Response, error) { + var requestStarted = time.Now() - for i := 0; i < maxRetry+1; i++ { + retryParams := a.client.cfg.RetryParams + for i := 0; i < retryParams.MaxRetry+1; i++ { var ( - localVarHTTPMethod = _nethttp.MethodGet + localVarHTTPMethod = http.MethodGet localVarPostBody interface{} localVarReturnValue ReadAssertionsResponse ) @@ -3624,15 +3714,15 @@ func (a *OpenFgaApiService) ReadAssertionsExecute(r ApiReadAssertionsRequest) (R return localVarReturnValue, nil, reportError("storeId is required and must be specified") } - localVarPath = strings.Replace(localVarPath, "{"+"store_id"+"}", _neturl.PathEscape(parameterToString(r.storeId, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"store_id"+"}", url.PathEscape(parameterToString(r.storeId, "")), -1) if r.authorizationModelId == "" { return localVarReturnValue, nil, reportError("authorizationModelId is required and must be specified") } - localVarPath = strings.Replace(localVarPath, "{"+"authorization_model_id"+"}", _neturl.PathEscape(parameterToString(r.authorizationModelId, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"authorization_model_id"+"}", url.PathEscape(parameterToString(r.authorizationModelId, "")), -1) localVarHeaderParams := make(map[string]string) - localVarQueryParams := _neturl.Values{} + localVarQueryParams := url.Values{} // to determine the Content-Type header localVarHTTPContentTypes := []string{} @@ -3658,19 +3748,33 @@ func (a *OpenFgaApiService) ReadAssertionsExecute(r ApiReadAssertionsRequest) (R localVarHTTPResponse, err := a.client.callAPI(req) if err != nil || localVarHTTPResponse == nil { + if i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, http.Header{}, "ReadAssertions") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } + } return localVarReturnValue, localVarHTTPResponse, err } - localVarBody, err := _ioutil.ReadAll(localVarHTTPResponse.Body) + localVarBody, err := io.ReadAll(localVarHTTPResponse.Body) localVarHTTPResponse.Body.Close() - localVarHTTPResponse.Body = _ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + localVarHTTPResponse.Body = io.NopCloser(bytes.NewBuffer(localVarBody)) if err != nil { + if i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, localVarHTTPResponse.Header, "ReadAssertions") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } + } return localVarReturnValue, localVarHTTPResponse, err } - if localVarHTTPResponse.StatusCode >= _nethttp.StatusMultipleChoices { + if localVarHTTPResponse.StatusCode >= http.StatusMultipleChoices { - if localVarHTTPResponse.StatusCode == _nethttp.StatusBadRequest || localVarHTTPResponse.StatusCode == _nethttp.StatusUnprocessableEntity { + if localVarHTTPResponse.StatusCode == http.StatusBadRequest || localVarHTTPResponse.StatusCode == http.StatusUnprocessableEntity { newErr := FgaApiValidationError{ body: localVarBody, storeId: r.storeId, @@ -3696,7 +3800,7 @@ func (a *OpenFgaApiService) ReadAssertionsExecute(r ApiReadAssertionsRequest) (R return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == _nethttp.StatusUnauthorized || localVarHTTPResponse.StatusCode == _nethttp.StatusForbidden { + if localVarHTTPResponse.StatusCode == http.StatusUnauthorized || localVarHTTPResponse.StatusCode == http.StatusForbidden { newErr := FgaApiAuthenticationError{ body: localVarBody, storeId: r.storeId, @@ -3711,7 +3815,7 @@ func (a *OpenFgaApiService) ReadAssertionsExecute(r ApiReadAssertionsRequest) (R return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == _nethttp.StatusNotFound { + if localVarHTTPResponse.StatusCode == http.StatusNotFound { newErr := FgaApiNotFoundError{ body: localVarBody, storeId: r.storeId, @@ -3737,10 +3841,13 @@ func (a *OpenFgaApiService) ReadAssertionsExecute(r ApiReadAssertionsRequest) (R return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == _nethttp.StatusTooManyRequests { - if i < maxRetry { - time.Sleep(time.Duration(internalutils.RandomTime(i, minWaitInMs)) * time.Millisecond) - continue + if localVarHTTPResponse.StatusCode == http.StatusTooManyRequests { + if i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, localVarHTTPResponse.Header, "ReadAssertions") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } } // maximum number of retry reached newErr := FgaApiRateLimitExceededError{ @@ -3759,10 +3866,13 @@ func (a *OpenFgaApiService) ReadAssertionsExecute(r ApiReadAssertionsRequest) (R return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode >= _nethttp.StatusInternalServerError { - if localVarHTTPResponse.StatusCode != _nethttp.StatusNotImplemented && i < maxRetry { - time.Sleep(time.Duration(internalutils.RandomTime(i, minWaitInMs)) * time.Millisecond) - continue + if localVarHTTPResponse.StatusCode >= http.StatusInternalServerError { + if localVarHTTPResponse.StatusCode != http.StatusNotImplemented && i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, localVarHTTPResponse.Header, "ReadAssertions") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } } newErr := FgaApiInternalError{ body: localVarBody, @@ -3852,13 +3962,13 @@ func (a *OpenFgaApiService) ReadAssertionsExecute(r ApiReadAssertionsRequest) (R } type ApiReadAuthorizationModelRequest struct { - ctx _context.Context + ctx context.Context ApiService OpenFgaApi storeId string id string } -func (r ApiReadAuthorizationModelRequest) Execute() (ReadAuthorizationModelResponse, *_nethttp.Response, error) { +func (r ApiReadAuthorizationModelRequest) Execute() (ReadAuthorizationModelResponse, *http.Response, error) { return r.ApiService.ReadAuthorizationModelExecute(r) } @@ -3908,12 +4018,12 @@ To retrieve the authorization model with ID `01G5JAVJ41T49E9TT3SKVS7X1J` for the ``` In the above example, there are 2 types (`user` and `document`). The `document` type has 2 relations (`writer` and `reader`). - - @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @param storeId - @param id - @return ApiReadAuthorizationModelRequest */ -func (a *OpenFgaApiService) ReadAuthorizationModel(ctx _context.Context, storeId string, id string) ApiReadAuthorizationModelRequest { +func (a *OpenFgaApiService) ReadAuthorizationModel(ctx context.Context, storeId string, id string) ApiReadAuthorizationModelRequest { return ApiReadAuthorizationModelRequest{ ApiService: a, ctx: ctx, @@ -3926,22 +4036,13 @@ func (a *OpenFgaApiService) ReadAuthorizationModel(ctx _context.Context, storeId * Execute executes the request * @return ReadAuthorizationModelResponse */ -func (a *OpenFgaApiService) ReadAuthorizationModelExecute(r ApiReadAuthorizationModelRequest) (ReadAuthorizationModelResponse, *_nethttp.Response, error) { - var maxRetry int - var minWaitInMs int - var requestStarted time.Time = time.Now() - - if a.RetryParams != nil { - maxRetry = a.RetryParams.MinWaitInMs - minWaitInMs = a.RetryParams.MinWaitInMs - } else { - maxRetry = 0 - minWaitInMs = 0 - } +func (a *OpenFgaApiService) ReadAuthorizationModelExecute(r ApiReadAuthorizationModelRequest) (ReadAuthorizationModelResponse, *http.Response, error) { + var requestStarted = time.Now() - for i := 0; i < maxRetry+1; i++ { + retryParams := a.client.cfg.RetryParams + for i := 0; i < retryParams.MaxRetry+1; i++ { var ( - localVarHTTPMethod = _nethttp.MethodGet + localVarHTTPMethod = http.MethodGet localVarPostBody interface{} localVarReturnValue ReadAuthorizationModelResponse ) @@ -3951,15 +4052,15 @@ func (a *OpenFgaApiService) ReadAuthorizationModelExecute(r ApiReadAuthorization return localVarReturnValue, nil, reportError("storeId is required and must be specified") } - localVarPath = strings.Replace(localVarPath, "{"+"store_id"+"}", _neturl.PathEscape(parameterToString(r.storeId, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"store_id"+"}", url.PathEscape(parameterToString(r.storeId, "")), -1) if r.id == "" { return localVarReturnValue, nil, reportError("id is required and must be specified") } - localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", _neturl.PathEscape(parameterToString(r.id, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterToString(r.id, "")), -1) localVarHeaderParams := make(map[string]string) - localVarQueryParams := _neturl.Values{} + localVarQueryParams := url.Values{} // to determine the Content-Type header localVarHTTPContentTypes := []string{} @@ -3985,19 +4086,33 @@ func (a *OpenFgaApiService) ReadAuthorizationModelExecute(r ApiReadAuthorization localVarHTTPResponse, err := a.client.callAPI(req) if err != nil || localVarHTTPResponse == nil { + if i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, http.Header{}, "ReadAuthorizationModel") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } + } return localVarReturnValue, localVarHTTPResponse, err } - localVarBody, err := _ioutil.ReadAll(localVarHTTPResponse.Body) + localVarBody, err := io.ReadAll(localVarHTTPResponse.Body) localVarHTTPResponse.Body.Close() - localVarHTTPResponse.Body = _ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + localVarHTTPResponse.Body = io.NopCloser(bytes.NewBuffer(localVarBody)) if err != nil { + if i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, localVarHTTPResponse.Header, "ReadAuthorizationModel") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } + } return localVarReturnValue, localVarHTTPResponse, err } - if localVarHTTPResponse.StatusCode >= _nethttp.StatusMultipleChoices { + if localVarHTTPResponse.StatusCode >= http.StatusMultipleChoices { - if localVarHTTPResponse.StatusCode == _nethttp.StatusBadRequest || localVarHTTPResponse.StatusCode == _nethttp.StatusUnprocessableEntity { + if localVarHTTPResponse.StatusCode == http.StatusBadRequest || localVarHTTPResponse.StatusCode == http.StatusUnprocessableEntity { newErr := FgaApiValidationError{ body: localVarBody, storeId: r.storeId, @@ -4023,7 +4138,7 @@ func (a *OpenFgaApiService) ReadAuthorizationModelExecute(r ApiReadAuthorization return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == _nethttp.StatusUnauthorized || localVarHTTPResponse.StatusCode == _nethttp.StatusForbidden { + if localVarHTTPResponse.StatusCode == http.StatusUnauthorized || localVarHTTPResponse.StatusCode == http.StatusForbidden { newErr := FgaApiAuthenticationError{ body: localVarBody, storeId: r.storeId, @@ -4038,7 +4153,7 @@ func (a *OpenFgaApiService) ReadAuthorizationModelExecute(r ApiReadAuthorization return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == _nethttp.StatusNotFound { + if localVarHTTPResponse.StatusCode == http.StatusNotFound { newErr := FgaApiNotFoundError{ body: localVarBody, storeId: r.storeId, @@ -4064,10 +4179,13 @@ func (a *OpenFgaApiService) ReadAuthorizationModelExecute(r ApiReadAuthorization return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == _nethttp.StatusTooManyRequests { - if i < maxRetry { - time.Sleep(time.Duration(internalutils.RandomTime(i, minWaitInMs)) * time.Millisecond) - continue + if localVarHTTPResponse.StatusCode == http.StatusTooManyRequests { + if i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, localVarHTTPResponse.Header, "ReadAuthorizationModel") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } } // maximum number of retry reached newErr := FgaApiRateLimitExceededError{ @@ -4086,10 +4204,13 @@ func (a *OpenFgaApiService) ReadAuthorizationModelExecute(r ApiReadAuthorization return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode >= _nethttp.StatusInternalServerError { - if localVarHTTPResponse.StatusCode != _nethttp.StatusNotImplemented && i < maxRetry { - time.Sleep(time.Duration(internalutils.RandomTime(i, minWaitInMs)) * time.Millisecond) - continue + if localVarHTTPResponse.StatusCode >= http.StatusInternalServerError { + if localVarHTTPResponse.StatusCode != http.StatusNotImplemented && i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, localVarHTTPResponse.Header, "ReadAuthorizationModel") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } } newErr := FgaApiInternalError{ body: localVarBody, @@ -4179,7 +4300,7 @@ func (a *OpenFgaApiService) ReadAuthorizationModelExecute(r ApiReadAuthorization } type ApiReadAuthorizationModelsRequest struct { - ctx _context.Context + ctx context.Context ApiService OpenFgaApi storeId string pageSize *int32 @@ -4195,7 +4316,7 @@ func (r ApiReadAuthorizationModelsRequest) ContinuationToken(continuationToken s return r } -func (r ApiReadAuthorizationModelsRequest) Execute() (ReadAuthorizationModelsResponse, *_nethttp.Response, error) { +func (r ApiReadAuthorizationModelsRequest) Execute() (ReadAuthorizationModelsResponse, *http.Response, error) { return r.ApiService.ReadAuthorizationModelsExecute(r) } @@ -4243,11 +4364,11 @@ If there are no more authorization models available, the `continuation_token` fi ``` - - @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @param storeId - @return ApiReadAuthorizationModelsRequest */ -func (a *OpenFgaApiService) ReadAuthorizationModels(ctx _context.Context, storeId string) ApiReadAuthorizationModelsRequest { +func (a *OpenFgaApiService) ReadAuthorizationModels(ctx context.Context, storeId string) ApiReadAuthorizationModelsRequest { return ApiReadAuthorizationModelsRequest{ ApiService: a, ctx: ctx, @@ -4259,22 +4380,13 @@ func (a *OpenFgaApiService) ReadAuthorizationModels(ctx _context.Context, storeI * Execute executes the request * @return ReadAuthorizationModelsResponse */ -func (a *OpenFgaApiService) ReadAuthorizationModelsExecute(r ApiReadAuthorizationModelsRequest) (ReadAuthorizationModelsResponse, *_nethttp.Response, error) { - var maxRetry int - var minWaitInMs int - var requestStarted time.Time = time.Now() - - if a.RetryParams != nil { - maxRetry = a.RetryParams.MinWaitInMs - minWaitInMs = a.RetryParams.MinWaitInMs - } else { - maxRetry = 0 - minWaitInMs = 0 - } +func (a *OpenFgaApiService) ReadAuthorizationModelsExecute(r ApiReadAuthorizationModelsRequest) (ReadAuthorizationModelsResponse, *http.Response, error) { + var requestStarted = time.Now() - for i := 0; i < maxRetry+1; i++ { + retryParams := a.client.cfg.RetryParams + for i := 0; i < retryParams.MaxRetry+1; i++ { var ( - localVarHTTPMethod = _nethttp.MethodGet + localVarHTTPMethod = http.MethodGet localVarPostBody interface{} localVarReturnValue ReadAuthorizationModelsResponse ) @@ -4284,10 +4396,10 @@ func (a *OpenFgaApiService) ReadAuthorizationModelsExecute(r ApiReadAuthorizatio return localVarReturnValue, nil, reportError("storeId is required and must be specified") } - localVarPath = strings.Replace(localVarPath, "{"+"store_id"+"}", _neturl.PathEscape(parameterToString(r.storeId, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"store_id"+"}", url.PathEscape(parameterToString(r.storeId, "")), -1) localVarHeaderParams := make(map[string]string) - localVarQueryParams := _neturl.Values{} + localVarQueryParams := url.Values{} if r.pageSize != nil { localVarQueryParams.Add("page_size", parameterToString(*r.pageSize, "")) @@ -4319,19 +4431,33 @@ func (a *OpenFgaApiService) ReadAuthorizationModelsExecute(r ApiReadAuthorizatio localVarHTTPResponse, err := a.client.callAPI(req) if err != nil || localVarHTTPResponse == nil { + if i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, http.Header{}, "ReadAuthorizationModels") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } + } return localVarReturnValue, localVarHTTPResponse, err } - localVarBody, err := _ioutil.ReadAll(localVarHTTPResponse.Body) + localVarBody, err := io.ReadAll(localVarHTTPResponse.Body) localVarHTTPResponse.Body.Close() - localVarHTTPResponse.Body = _ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + localVarHTTPResponse.Body = io.NopCloser(bytes.NewBuffer(localVarBody)) if err != nil { + if i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, localVarHTTPResponse.Header, "ReadAuthorizationModels") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } + } return localVarReturnValue, localVarHTTPResponse, err } - if localVarHTTPResponse.StatusCode >= _nethttp.StatusMultipleChoices { + if localVarHTTPResponse.StatusCode >= http.StatusMultipleChoices { - if localVarHTTPResponse.StatusCode == _nethttp.StatusBadRequest || localVarHTTPResponse.StatusCode == _nethttp.StatusUnprocessableEntity { + if localVarHTTPResponse.StatusCode == http.StatusBadRequest || localVarHTTPResponse.StatusCode == http.StatusUnprocessableEntity { newErr := FgaApiValidationError{ body: localVarBody, storeId: r.storeId, @@ -4357,7 +4483,7 @@ func (a *OpenFgaApiService) ReadAuthorizationModelsExecute(r ApiReadAuthorizatio return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == _nethttp.StatusUnauthorized || localVarHTTPResponse.StatusCode == _nethttp.StatusForbidden { + if localVarHTTPResponse.StatusCode == http.StatusUnauthorized || localVarHTTPResponse.StatusCode == http.StatusForbidden { newErr := FgaApiAuthenticationError{ body: localVarBody, storeId: r.storeId, @@ -4372,7 +4498,7 @@ func (a *OpenFgaApiService) ReadAuthorizationModelsExecute(r ApiReadAuthorizatio return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == _nethttp.StatusNotFound { + if localVarHTTPResponse.StatusCode == http.StatusNotFound { newErr := FgaApiNotFoundError{ body: localVarBody, storeId: r.storeId, @@ -4398,10 +4524,13 @@ func (a *OpenFgaApiService) ReadAuthorizationModelsExecute(r ApiReadAuthorizatio return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == _nethttp.StatusTooManyRequests { - if i < maxRetry { - time.Sleep(time.Duration(internalutils.RandomTime(i, minWaitInMs)) * time.Millisecond) - continue + if localVarHTTPResponse.StatusCode == http.StatusTooManyRequests { + if i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, localVarHTTPResponse.Header, "ReadAuthorizationModels") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } } // maximum number of retry reached newErr := FgaApiRateLimitExceededError{ @@ -4420,10 +4549,13 @@ func (a *OpenFgaApiService) ReadAuthorizationModelsExecute(r ApiReadAuthorizatio return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode >= _nethttp.StatusInternalServerError { - if localVarHTTPResponse.StatusCode != _nethttp.StatusNotImplemented && i < maxRetry { - time.Sleep(time.Duration(internalutils.RandomTime(i, minWaitInMs)) * time.Millisecond) - continue + if localVarHTTPResponse.StatusCode >= http.StatusInternalServerError { + if localVarHTTPResponse.StatusCode != http.StatusNotImplemented && i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, localVarHTTPResponse.Header, "ReadAuthorizationModels") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } } newErr := FgaApiInternalError{ body: localVarBody, @@ -4513,7 +4645,7 @@ func (a *OpenFgaApiService) ReadAuthorizationModelsExecute(r ApiReadAuthorizatio } type ApiReadChangesRequest struct { - ctx _context.Context + ctx context.Context ApiService OpenFgaApi storeId string type_ *string @@ -4539,7 +4671,7 @@ func (r ApiReadChangesRequest) StartTime(startTime time.Time) ApiReadChangesRequ return r } -func (r ApiReadChangesRequest) Execute() (ReadChangesResponse, *_nethttp.Response, error) { +func (r ApiReadChangesRequest) Execute() (ReadChangesResponse, *http.Response, error) { return r.ApiService.ReadChangesExecute(r) } @@ -4551,11 +4683,11 @@ You can use the `type` parameter to only get the list of tuple changes that affe When reading a write tuple change, if it was conditioned, the condition will be returned. When reading a delete tuple change, the condition will NOT be returned regardless of whether it was originally conditioned or not. - - @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @param storeId - @return ApiReadChangesRequest */ -func (a *OpenFgaApiService) ReadChanges(ctx _context.Context, storeId string) ApiReadChangesRequest { +func (a *OpenFgaApiService) ReadChanges(ctx context.Context, storeId string) ApiReadChangesRequest { return ApiReadChangesRequest{ ApiService: a, ctx: ctx, @@ -4567,22 +4699,13 @@ func (a *OpenFgaApiService) ReadChanges(ctx _context.Context, storeId string) Ap * Execute executes the request * @return ReadChangesResponse */ -func (a *OpenFgaApiService) ReadChangesExecute(r ApiReadChangesRequest) (ReadChangesResponse, *_nethttp.Response, error) { - var maxRetry int - var minWaitInMs int - var requestStarted time.Time = time.Now() - - if a.RetryParams != nil { - maxRetry = a.RetryParams.MinWaitInMs - minWaitInMs = a.RetryParams.MinWaitInMs - } else { - maxRetry = 0 - minWaitInMs = 0 - } +func (a *OpenFgaApiService) ReadChangesExecute(r ApiReadChangesRequest) (ReadChangesResponse, *http.Response, error) { + var requestStarted = time.Now() - for i := 0; i < maxRetry+1; i++ { + retryParams := a.client.cfg.RetryParams + for i := 0; i < retryParams.MaxRetry+1; i++ { var ( - localVarHTTPMethod = _nethttp.MethodGet + localVarHTTPMethod = http.MethodGet localVarPostBody interface{} localVarReturnValue ReadChangesResponse ) @@ -4592,10 +4715,10 @@ func (a *OpenFgaApiService) ReadChangesExecute(r ApiReadChangesRequest) (ReadCha return localVarReturnValue, nil, reportError("storeId is required and must be specified") } - localVarPath = strings.Replace(localVarPath, "{"+"store_id"+"}", _neturl.PathEscape(parameterToString(r.storeId, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"store_id"+"}", url.PathEscape(parameterToString(r.storeId, "")), -1) localVarHeaderParams := make(map[string]string) - localVarQueryParams := _neturl.Values{} + localVarQueryParams := url.Values{} if r.type_ != nil { localVarQueryParams.Add("type", parameterToString(*r.type_, "")) @@ -4633,19 +4756,33 @@ func (a *OpenFgaApiService) ReadChangesExecute(r ApiReadChangesRequest) (ReadCha localVarHTTPResponse, err := a.client.callAPI(req) if err != nil || localVarHTTPResponse == nil { + if i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, http.Header{}, "ReadChanges") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } + } return localVarReturnValue, localVarHTTPResponse, err } - localVarBody, err := _ioutil.ReadAll(localVarHTTPResponse.Body) + localVarBody, err := io.ReadAll(localVarHTTPResponse.Body) localVarHTTPResponse.Body.Close() - localVarHTTPResponse.Body = _ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + localVarHTTPResponse.Body = io.NopCloser(bytes.NewBuffer(localVarBody)) if err != nil { + if i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, localVarHTTPResponse.Header, "ReadChanges") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } + } return localVarReturnValue, localVarHTTPResponse, err } - if localVarHTTPResponse.StatusCode >= _nethttp.StatusMultipleChoices { + if localVarHTTPResponse.StatusCode >= http.StatusMultipleChoices { - if localVarHTTPResponse.StatusCode == _nethttp.StatusBadRequest || localVarHTTPResponse.StatusCode == _nethttp.StatusUnprocessableEntity { + if localVarHTTPResponse.StatusCode == http.StatusBadRequest || localVarHTTPResponse.StatusCode == http.StatusUnprocessableEntity { newErr := FgaApiValidationError{ body: localVarBody, storeId: r.storeId, @@ -4671,7 +4808,7 @@ func (a *OpenFgaApiService) ReadChangesExecute(r ApiReadChangesRequest) (ReadCha return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == _nethttp.StatusUnauthorized || localVarHTTPResponse.StatusCode == _nethttp.StatusForbidden { + if localVarHTTPResponse.StatusCode == http.StatusUnauthorized || localVarHTTPResponse.StatusCode == http.StatusForbidden { newErr := FgaApiAuthenticationError{ body: localVarBody, storeId: r.storeId, @@ -4686,7 +4823,7 @@ func (a *OpenFgaApiService) ReadChangesExecute(r ApiReadChangesRequest) (ReadCha return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == _nethttp.StatusNotFound { + if localVarHTTPResponse.StatusCode == http.StatusNotFound { newErr := FgaApiNotFoundError{ body: localVarBody, storeId: r.storeId, @@ -4712,10 +4849,13 @@ func (a *OpenFgaApiService) ReadChangesExecute(r ApiReadChangesRequest) (ReadCha return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == _nethttp.StatusTooManyRequests { - if i < maxRetry { - time.Sleep(time.Duration(internalutils.RandomTime(i, minWaitInMs)) * time.Millisecond) - continue + if localVarHTTPResponse.StatusCode == http.StatusTooManyRequests { + if i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, localVarHTTPResponse.Header, "ReadChanges") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } } // maximum number of retry reached newErr := FgaApiRateLimitExceededError{ @@ -4734,10 +4874,13 @@ func (a *OpenFgaApiService) ReadChangesExecute(r ApiReadChangesRequest) (ReadCha return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode >= _nethttp.StatusInternalServerError { - if localVarHTTPResponse.StatusCode != _nethttp.StatusNotImplemented && i < maxRetry { - time.Sleep(time.Duration(internalutils.RandomTime(i, minWaitInMs)) * time.Millisecond) - continue + if localVarHTTPResponse.StatusCode >= http.StatusInternalServerError { + if localVarHTTPResponse.StatusCode != http.StatusNotImplemented && i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, localVarHTTPResponse.Header, "ReadChanges") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } } newErr := FgaApiInternalError{ body: localVarBody, @@ -4827,7 +4970,7 @@ func (a *OpenFgaApiService) ReadChangesExecute(r ApiReadChangesRequest) (ReadCha } type ApiWriteRequest struct { - ctx _context.Context + ctx context.Context ApiService OpenFgaApi storeId string body *WriteRequest @@ -4838,7 +4981,7 @@ func (r ApiWriteRequest) Body(body WriteRequest) ApiWriteRequest { return r } -func (r ApiWriteRequest) Execute() (map[string]interface{}, *_nethttp.Response, error) { +func (r ApiWriteRequest) Execute() (map[string]interface{}, *http.Response, error) { return r.ApiService.WriteExecute(r) } @@ -4887,11 +5030,11 @@ To remove `user:bob` as a `reader` for `document:2021-budget`, call write API wi ``` - - @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @param storeId - @return ApiWriteRequest */ -func (a *OpenFgaApiService) Write(ctx _context.Context, storeId string) ApiWriteRequest { +func (a *OpenFgaApiService) Write(ctx context.Context, storeId string) ApiWriteRequest { return ApiWriteRequest{ ApiService: a, ctx: ctx, @@ -4903,22 +5046,13 @@ func (a *OpenFgaApiService) Write(ctx _context.Context, storeId string) ApiWrite * Execute executes the request * @return map[string]interface{} */ -func (a *OpenFgaApiService) WriteExecute(r ApiWriteRequest) (map[string]interface{}, *_nethttp.Response, error) { - var maxRetry int - var minWaitInMs int - var requestStarted time.Time = time.Now() - - if a.RetryParams != nil { - maxRetry = a.RetryParams.MinWaitInMs - minWaitInMs = a.RetryParams.MinWaitInMs - } else { - maxRetry = 0 - minWaitInMs = 0 - } +func (a *OpenFgaApiService) WriteExecute(r ApiWriteRequest) (map[string]interface{}, *http.Response, error) { + var requestStarted = time.Now() - for i := 0; i < maxRetry+1; i++ { + retryParams := a.client.cfg.RetryParams + for i := 0; i < retryParams.MaxRetry+1; i++ { var ( - localVarHTTPMethod = _nethttp.MethodPost + localVarHTTPMethod = http.MethodPost localVarPostBody interface{} localVarReturnValue map[string]interface{} ) @@ -4928,10 +5062,10 @@ func (a *OpenFgaApiService) WriteExecute(r ApiWriteRequest) (map[string]interfac return localVarReturnValue, nil, reportError("storeId is required and must be specified") } - localVarPath = strings.Replace(localVarPath, "{"+"store_id"+"}", _neturl.PathEscape(parameterToString(r.storeId, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"store_id"+"}", url.PathEscape(parameterToString(r.storeId, "")), -1) localVarHeaderParams := make(map[string]string) - localVarQueryParams := _neturl.Values{} + localVarQueryParams := url.Values{} if r.body == nil { return localVarReturnValue, nil, reportError("body is required and must be specified") } @@ -4962,19 +5096,33 @@ func (a *OpenFgaApiService) WriteExecute(r ApiWriteRequest) (map[string]interfac localVarHTTPResponse, err := a.client.callAPI(req) if err != nil || localVarHTTPResponse == nil { + if i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, http.Header{}, "Write") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } + } return localVarReturnValue, localVarHTTPResponse, err } - localVarBody, err := _ioutil.ReadAll(localVarHTTPResponse.Body) + localVarBody, err := io.ReadAll(localVarHTTPResponse.Body) localVarHTTPResponse.Body.Close() - localVarHTTPResponse.Body = _ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + localVarHTTPResponse.Body = io.NopCloser(bytes.NewBuffer(localVarBody)) if err != nil { + if i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, localVarHTTPResponse.Header, "Write") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } + } return localVarReturnValue, localVarHTTPResponse, err } - if localVarHTTPResponse.StatusCode >= _nethttp.StatusMultipleChoices { + if localVarHTTPResponse.StatusCode >= http.StatusMultipleChoices { - if localVarHTTPResponse.StatusCode == _nethttp.StatusBadRequest || localVarHTTPResponse.StatusCode == _nethttp.StatusUnprocessableEntity { + if localVarHTTPResponse.StatusCode == http.StatusBadRequest || localVarHTTPResponse.StatusCode == http.StatusUnprocessableEntity { newErr := FgaApiValidationError{ body: localVarBody, storeId: r.storeId, @@ -5000,7 +5148,7 @@ func (a *OpenFgaApiService) WriteExecute(r ApiWriteRequest) (map[string]interfac return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == _nethttp.StatusUnauthorized || localVarHTTPResponse.StatusCode == _nethttp.StatusForbidden { + if localVarHTTPResponse.StatusCode == http.StatusUnauthorized || localVarHTTPResponse.StatusCode == http.StatusForbidden { newErr := FgaApiAuthenticationError{ body: localVarBody, storeId: r.storeId, @@ -5015,7 +5163,7 @@ func (a *OpenFgaApiService) WriteExecute(r ApiWriteRequest) (map[string]interfac return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == _nethttp.StatusNotFound { + if localVarHTTPResponse.StatusCode == http.StatusNotFound { newErr := FgaApiNotFoundError{ body: localVarBody, storeId: r.storeId, @@ -5041,10 +5189,13 @@ func (a *OpenFgaApiService) WriteExecute(r ApiWriteRequest) (map[string]interfac return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == _nethttp.StatusTooManyRequests { - if i < maxRetry { - time.Sleep(time.Duration(internalutils.RandomTime(i, minWaitInMs)) * time.Millisecond) - continue + if localVarHTTPResponse.StatusCode == http.StatusTooManyRequests { + if i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, localVarHTTPResponse.Header, "Write") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } } // maximum number of retry reached newErr := FgaApiRateLimitExceededError{ @@ -5063,10 +5214,13 @@ func (a *OpenFgaApiService) WriteExecute(r ApiWriteRequest) (map[string]interfac return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode >= _nethttp.StatusInternalServerError { - if localVarHTTPResponse.StatusCode != _nethttp.StatusNotImplemented && i < maxRetry { - time.Sleep(time.Duration(internalutils.RandomTime(i, minWaitInMs)) * time.Millisecond) - continue + if localVarHTTPResponse.StatusCode >= http.StatusInternalServerError { + if localVarHTTPResponse.StatusCode != http.StatusNotImplemented && i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, localVarHTTPResponse.Header, "Write") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } } newErr := FgaApiInternalError{ body: localVarBody, @@ -5156,7 +5310,7 @@ func (a *OpenFgaApiService) WriteExecute(r ApiWriteRequest) (map[string]interfac } type ApiWriteAssertionsRequest struct { - ctx _context.Context + ctx context.Context ApiService OpenFgaApi storeId string authorizationModelId string @@ -5168,19 +5322,19 @@ func (r ApiWriteAssertionsRequest) Body(body WriteAssertionsRequest) ApiWriteAss return r } -func (r ApiWriteAssertionsRequest) Execute() (*_nethttp.Response, error) { +func (r ApiWriteAssertionsRequest) Execute() (*http.Response, error) { return r.ApiService.WriteAssertionsExecute(r) } /* * WriteAssertions Upsert assertions for an authorization model ID * The WriteAssertions API will upsert new assertions for an authorization model id, or overwrite the existing ones. An assertion is an object that contains a tuple key, the expectation of whether a call to the Check API of that tuple key will return true or false, and optionally a list of contextual tuples. - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). * @param storeId * @param authorizationModelId * @return ApiWriteAssertionsRequest */ -func (a *OpenFgaApiService) WriteAssertions(ctx _context.Context, storeId string, authorizationModelId string) ApiWriteAssertionsRequest { +func (a *OpenFgaApiService) WriteAssertions(ctx context.Context, storeId string, authorizationModelId string) ApiWriteAssertionsRequest { return ApiWriteAssertionsRequest{ ApiService: a, ctx: ctx, @@ -5192,22 +5346,13 @@ func (a *OpenFgaApiService) WriteAssertions(ctx _context.Context, storeId string /* * Execute executes the request */ -func (a *OpenFgaApiService) WriteAssertionsExecute(r ApiWriteAssertionsRequest) (*_nethttp.Response, error) { - var maxRetry int - var minWaitInMs int - var requestStarted time.Time = time.Now() - - if a.RetryParams != nil { - maxRetry = a.RetryParams.MinWaitInMs - minWaitInMs = a.RetryParams.MinWaitInMs - } else { - maxRetry = 0 - minWaitInMs = 0 - } +func (a *OpenFgaApiService) WriteAssertionsExecute(r ApiWriteAssertionsRequest) (*http.Response, error) { + var requestStarted = time.Now() - for i := 0; i < maxRetry+1; i++ { + retryParams := a.client.cfg.RetryParams + for i := 0; i < retryParams.MaxRetry+1; i++ { var ( - localVarHTTPMethod = _nethttp.MethodPut + localVarHTTPMethod = http.MethodPut localVarPostBody interface{} ) @@ -5216,15 +5361,15 @@ func (a *OpenFgaApiService) WriteAssertionsExecute(r ApiWriteAssertionsRequest) return nil, reportError("storeId is required and must be specified") } - localVarPath = strings.Replace(localVarPath, "{"+"store_id"+"}", _neturl.PathEscape(parameterToString(r.storeId, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"store_id"+"}", url.PathEscape(parameterToString(r.storeId, "")), -1) if r.authorizationModelId == "" { return nil, reportError("authorizationModelId is required and must be specified") } - localVarPath = strings.Replace(localVarPath, "{"+"authorization_model_id"+"}", _neturl.PathEscape(parameterToString(r.authorizationModelId, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"authorization_model_id"+"}", url.PathEscape(parameterToString(r.authorizationModelId, "")), -1) localVarHeaderParams := make(map[string]string) - localVarQueryParams := _neturl.Values{} + localVarQueryParams := url.Values{} if r.body == nil { return nil, reportError("body is required and must be specified") } @@ -5255,19 +5400,33 @@ func (a *OpenFgaApiService) WriteAssertionsExecute(r ApiWriteAssertionsRequest) localVarHTTPResponse, err := a.client.callAPI(req) if err != nil || localVarHTTPResponse == nil { + if i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, http.Header{}, "WriteAssertions") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } + } return localVarHTTPResponse, err } - localVarBody, err := _ioutil.ReadAll(localVarHTTPResponse.Body) + localVarBody, err := io.ReadAll(localVarHTTPResponse.Body) localVarHTTPResponse.Body.Close() - localVarHTTPResponse.Body = _ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + localVarHTTPResponse.Body = io.NopCloser(bytes.NewBuffer(localVarBody)) if err != nil { + if i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, localVarHTTPResponse.Header, "WriteAssertions") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } + } return localVarHTTPResponse, err } - if localVarHTTPResponse.StatusCode >= _nethttp.StatusMultipleChoices { + if localVarHTTPResponse.StatusCode >= http.StatusMultipleChoices { - if localVarHTTPResponse.StatusCode == _nethttp.StatusBadRequest || localVarHTTPResponse.StatusCode == _nethttp.StatusUnprocessableEntity { + if localVarHTTPResponse.StatusCode == http.StatusBadRequest || localVarHTTPResponse.StatusCode == http.StatusUnprocessableEntity { newErr := FgaApiValidationError{ body: localVarBody, storeId: r.storeId, @@ -5293,7 +5452,7 @@ func (a *OpenFgaApiService) WriteAssertionsExecute(r ApiWriteAssertionsRequest) return localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == _nethttp.StatusUnauthorized || localVarHTTPResponse.StatusCode == _nethttp.StatusForbidden { + if localVarHTTPResponse.StatusCode == http.StatusUnauthorized || localVarHTTPResponse.StatusCode == http.StatusForbidden { newErr := FgaApiAuthenticationError{ body: localVarBody, storeId: r.storeId, @@ -5308,7 +5467,7 @@ func (a *OpenFgaApiService) WriteAssertionsExecute(r ApiWriteAssertionsRequest) return localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == _nethttp.StatusNotFound { + if localVarHTTPResponse.StatusCode == http.StatusNotFound { newErr := FgaApiNotFoundError{ body: localVarBody, storeId: r.storeId, @@ -5334,10 +5493,13 @@ func (a *OpenFgaApiService) WriteAssertionsExecute(r ApiWriteAssertionsRequest) return localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == _nethttp.StatusTooManyRequests { - if i < maxRetry { - time.Sleep(time.Duration(internalutils.RandomTime(i, minWaitInMs)) * time.Millisecond) - continue + if localVarHTTPResponse.StatusCode == http.StatusTooManyRequests { + if i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, localVarHTTPResponse.Header, "WriteAssertions") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } } // maximum number of retry reached newErr := FgaApiRateLimitExceededError{ @@ -5356,10 +5518,13 @@ func (a *OpenFgaApiService) WriteAssertionsExecute(r ApiWriteAssertionsRequest) return localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode >= _nethttp.StatusInternalServerError { - if localVarHTTPResponse.StatusCode != _nethttp.StatusNotImplemented && i < maxRetry { - time.Sleep(time.Duration(internalutils.RandomTime(i, minWaitInMs)) * time.Millisecond) - continue + if localVarHTTPResponse.StatusCode >= http.StatusInternalServerError { + if localVarHTTPResponse.StatusCode != http.StatusNotImplemented && i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, localVarHTTPResponse.Header, "WriteAssertions") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } } newErr := FgaApiInternalError{ body: localVarBody, @@ -5439,7 +5604,7 @@ func (a *OpenFgaApiService) WriteAssertionsExecute(r ApiWriteAssertionsRequest) } type ApiWriteAuthorizationModelRequest struct { - ctx _context.Context + ctx context.Context ApiService OpenFgaApi storeId string body *WriteAuthorizationModelRequest @@ -5450,7 +5615,7 @@ func (r ApiWriteAuthorizationModelRequest) Body(body WriteAuthorizationModelRequ return r } -func (r ApiWriteAuthorizationModelRequest) Execute() (WriteAuthorizationModelResponse, *_nethttp.Response, error) { +func (r ApiWriteAuthorizationModelRequest) Execute() (WriteAuthorizationModelResponse, *http.Response, error) { return r.ApiService.WriteAuthorizationModelExecute(r) } @@ -5502,11 +5667,11 @@ OpenFGA's response will include the version id for this authorization model, whi {"authorization_model_id": "01G50QVV17PECNVAHX1GG4Y5NC"} ``` - - @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @param storeId - @return ApiWriteAuthorizationModelRequest */ -func (a *OpenFgaApiService) WriteAuthorizationModel(ctx _context.Context, storeId string) ApiWriteAuthorizationModelRequest { +func (a *OpenFgaApiService) WriteAuthorizationModel(ctx context.Context, storeId string) ApiWriteAuthorizationModelRequest { return ApiWriteAuthorizationModelRequest{ ApiService: a, ctx: ctx, @@ -5518,22 +5683,13 @@ func (a *OpenFgaApiService) WriteAuthorizationModel(ctx _context.Context, storeI * Execute executes the request * @return WriteAuthorizationModelResponse */ -func (a *OpenFgaApiService) WriteAuthorizationModelExecute(r ApiWriteAuthorizationModelRequest) (WriteAuthorizationModelResponse, *_nethttp.Response, error) { - var maxRetry int - var minWaitInMs int - var requestStarted time.Time = time.Now() - - if a.RetryParams != nil { - maxRetry = a.RetryParams.MinWaitInMs - minWaitInMs = a.RetryParams.MinWaitInMs - } else { - maxRetry = 0 - minWaitInMs = 0 - } +func (a *OpenFgaApiService) WriteAuthorizationModelExecute(r ApiWriteAuthorizationModelRequest) (WriteAuthorizationModelResponse, *http.Response, error) { + var requestStarted = time.Now() - for i := 0; i < maxRetry+1; i++ { + retryParams := a.client.cfg.RetryParams + for i := 0; i < retryParams.MaxRetry+1; i++ { var ( - localVarHTTPMethod = _nethttp.MethodPost + localVarHTTPMethod = http.MethodPost localVarPostBody interface{} localVarReturnValue WriteAuthorizationModelResponse ) @@ -5543,10 +5699,10 @@ func (a *OpenFgaApiService) WriteAuthorizationModelExecute(r ApiWriteAuthorizati return localVarReturnValue, nil, reportError("storeId is required and must be specified") } - localVarPath = strings.Replace(localVarPath, "{"+"store_id"+"}", _neturl.PathEscape(parameterToString(r.storeId, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"store_id"+"}", url.PathEscape(parameterToString(r.storeId, "")), -1) localVarHeaderParams := make(map[string]string) - localVarQueryParams := _neturl.Values{} + localVarQueryParams := url.Values{} if r.body == nil { return localVarReturnValue, nil, reportError("body is required and must be specified") } @@ -5577,19 +5733,33 @@ func (a *OpenFgaApiService) WriteAuthorizationModelExecute(r ApiWriteAuthorizati localVarHTTPResponse, err := a.client.callAPI(req) if err != nil || localVarHTTPResponse == nil { + if i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, http.Header{}, "WriteAuthorizationModel") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } + } return localVarReturnValue, localVarHTTPResponse, err } - localVarBody, err := _ioutil.ReadAll(localVarHTTPResponse.Body) + localVarBody, err := io.ReadAll(localVarHTTPResponse.Body) localVarHTTPResponse.Body.Close() - localVarHTTPResponse.Body = _ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + localVarHTTPResponse.Body = io.NopCloser(bytes.NewBuffer(localVarBody)) if err != nil { + if i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, localVarHTTPResponse.Header, "WriteAuthorizationModel") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } + } return localVarReturnValue, localVarHTTPResponse, err } - if localVarHTTPResponse.StatusCode >= _nethttp.StatusMultipleChoices { + if localVarHTTPResponse.StatusCode >= http.StatusMultipleChoices { - if localVarHTTPResponse.StatusCode == _nethttp.StatusBadRequest || localVarHTTPResponse.StatusCode == _nethttp.StatusUnprocessableEntity { + if localVarHTTPResponse.StatusCode == http.StatusBadRequest || localVarHTTPResponse.StatusCode == http.StatusUnprocessableEntity { newErr := FgaApiValidationError{ body: localVarBody, storeId: r.storeId, @@ -5615,7 +5785,7 @@ func (a *OpenFgaApiService) WriteAuthorizationModelExecute(r ApiWriteAuthorizati return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == _nethttp.StatusUnauthorized || localVarHTTPResponse.StatusCode == _nethttp.StatusForbidden { + if localVarHTTPResponse.StatusCode == http.StatusUnauthorized || localVarHTTPResponse.StatusCode == http.StatusForbidden { newErr := FgaApiAuthenticationError{ body: localVarBody, storeId: r.storeId, @@ -5630,7 +5800,7 @@ func (a *OpenFgaApiService) WriteAuthorizationModelExecute(r ApiWriteAuthorizati return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == _nethttp.StatusNotFound { + if localVarHTTPResponse.StatusCode == http.StatusNotFound { newErr := FgaApiNotFoundError{ body: localVarBody, storeId: r.storeId, @@ -5656,10 +5826,13 @@ func (a *OpenFgaApiService) WriteAuthorizationModelExecute(r ApiWriteAuthorizati return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == _nethttp.StatusTooManyRequests { - if i < maxRetry { - time.Sleep(time.Duration(internalutils.RandomTime(i, minWaitInMs)) * time.Millisecond) - continue + if localVarHTTPResponse.StatusCode == http.StatusTooManyRequests { + if i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, localVarHTTPResponse.Header, "WriteAuthorizationModel") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } } // maximum number of retry reached newErr := FgaApiRateLimitExceededError{ @@ -5678,10 +5851,13 @@ func (a *OpenFgaApiService) WriteAuthorizationModelExecute(r ApiWriteAuthorizati return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode >= _nethttp.StatusInternalServerError { - if localVarHTTPResponse.StatusCode != _nethttp.StatusNotImplemented && i < maxRetry { - time.Sleep(time.Duration(internalutils.RandomTime(i, minWaitInMs)) * time.Millisecond) - continue + if localVarHTTPResponse.StatusCode >= http.StatusInternalServerError { + if localVarHTTPResponse.StatusCode != http.StatusNotImplemented && i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, localVarHTTPResponse.Header, "WriteAuthorizationModel") + if timeToWait > 0 { + time.Sleep(timeToWait) + continue + } } newErr := FgaApiInternalError{ body: localVarBody, diff --git a/api_open_fga_test.go b/api_open_fga_test.go index 9a56b47..e369d15 100644 --- a/api_open_fga_test.go +++ b/api_open_fga_test.go @@ -21,7 +21,9 @@ import ( "time" "github.com/jarcoal/httpmock" + "github.com/openfga/go-sdk/credentials" + "github.com/openfga/go-sdk/internal/utils/retryutils" ) type TestDefinition struct { @@ -61,6 +63,126 @@ func TestOpenFgaApiConfiguration(t *testing.T) { } }) + t.Run("RetryParams should be valid", func(t *testing.T) { + tests := []struct { + retryParams *RetryParams + expectedError bool + }{ + { + retryParams: &RetryParams{ + MaxRetry: 1, + MinWaitInMs: 0, + }, + expectedError: true, + }, + { + retryParams: &RetryParams{ + MaxRetry: 100, + MinWaitInMs: 1, + }, + expectedError: true, + }, + { + retryParams: &RetryParams{ + MaxRetry: -1, + MinWaitInMs: 1, + }, + expectedError: true, + }, + { + retryParams: &RetryParams{ + MaxRetry: 1, + MinWaitInMs: -1, + }, + expectedError: true, + }, + { + retryParams: &RetryParams{ + MaxRetry: 1, + MinWaitInMs: -1, + }, + expectedError: true, + }, + { + retryParams: &RetryParams{ + MaxRetry: 1, + MinWaitInMs: 1, + }, + expectedError: false, + }, + { + retryParams: &RetryParams{ + MaxRetry: 0, + MinWaitInMs: 1, + }, + expectedError: false, + }, + } + + for _, test := range tests { + t.Run(fmt.Sprintf("RetryParams: %v", *test.retryParams), func(t *testing.T) { + config, err := NewConfiguration(Configuration{ + ApiUrl: "https://api.fga.example", + RetryParams: test.retryParams, + }) + + if test.expectedError && err == nil { + t.Fatalf("Expected an error when RetryParams are invalid, got none") + } + + if !test.expectedError && err != nil { + t.Fatalf("Unexpected error: %v", err) + } + + if !test.expectedError { + if config.RetryParams == nil { + t.Fatalf("Expected RetryParams on the config to be non-nil") + } + + appliedRetryParams := *config.RetryParams + if appliedRetryParams.MaxRetry != test.retryParams.MaxRetry { + t.Fatalf("Expected MaxRetry to be %v, got %v", test.retryParams.MaxRetry, appliedRetryParams.MaxRetry) + } + + if appliedRetryParams.MinWaitInMs != test.retryParams.MinWaitInMs { + t.Fatalf("Expected MinWaitInMs to be %v, got %v", test.retryParams.MinWaitInMs, appliedRetryParams.MinWaitInMs) + } + + appliedRetryParams = config.GetRetryParams() + if appliedRetryParams.MaxRetry != test.retryParams.MaxRetry { + t.Fatalf("Expected MaxRetry to be %v, got %v", test.retryParams.MaxRetry, appliedRetryParams.MaxRetry) + } + + if appliedRetryParams.MinWaitInMs != test.retryParams.MinWaitInMs { + t.Fatalf("Expected MinWaitInMs to be %v, got %v", test.retryParams.MinWaitInMs, appliedRetryParams.MinWaitInMs) + } + } + }) + } + }) + + t.Run("RetryParams is default if not set", func(t *testing.T) { + config, err := NewConfiguration(Configuration{ + ApiUrl: "https://api.fga.example", + }) + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } + if config.RetryParams == nil { + t.Fatalf("Expected RetryParams on the config to be non-nil") + } + + appliedRetryParams := config.GetRetryParams() + defaultParams := retryutils.GetRetryParamsOrDefault(nil) + if appliedRetryParams.MaxRetry != defaultParams.MaxRetry { + t.Fatalf("Expected MaxRetry to be %v, got %v", defaultParams.MaxRetry, appliedRetryParams.MaxRetry) + } + + if appliedRetryParams.MinWaitInMs != defaultParams.MinWaitInMs { + t.Fatalf("Expected MinWaitInMs to be %v, got %v", defaultParams.MinWaitInMs, appliedRetryParams.MinWaitInMs) + } + }) + t.Run("In ApiToken credential method, apiToken is required in the Credentials Config", func(t *testing.T) { _, err := NewConfiguration(Configuration{ ApiHost: "https://api.fga.example", @@ -1256,7 +1378,7 @@ func TestOpenFgaApi(t *testing.T) { updatedConfiguration, err := NewConfiguration(Configuration{ ApiHost: "api.fga.example", RetryParams: &RetryParams{ - MaxRetry: 2, + MaxRetry: 3, MinWaitInMs: 5, }, }) @@ -1286,6 +1408,55 @@ func TestOpenFgaApi(t *testing.T) { } }) + t.Run("Check with initial 429 but eventually resolved with default config", func(t *testing.T) { + test := TestDefinition{ + Name: "Check", + JsonResponse: `{"allowed":true, "resolution":""}`, + ResponseStatus: 200, + Method: "POST", + RequestPath: "check", + } + requestBody := CheckRequest{ + TupleKey: CheckRequestTupleKey{ + User: "user:81684243-9356-4421-8fbf-a4f8d36aa31b", + Relation: "viewer", + Object: "document:0192ab2a-d83f-756d-9397-c5ed9f3cb69a", + }, + } + + var expectedResponse CheckResponse + if err := json.Unmarshal([]byte(test.JsonResponse), &expectedResponse); err != nil { + t.Fatalf("%v", err) + } + + httpmock.Activate() + defer httpmock.DeactivateAndReset() + firstMock := httpmock.NewStringResponder(429, "") + secondMock, _ := httpmock.NewJsonResponder(200, expectedResponse) + httpmock.RegisterResponder(test.Method, fmt.Sprintf("%s/stores/%s/%s", configuration.ApiUrl, "01GXSB9YR785C4FYS3C0RTG7B2", test.RequestPath), + firstMock.Then(secondMock), + ) + + got, response, err := apiClient.OpenFgaApi.Check(context.Background(), "01GXSB9YR785C4FYS3C0RTG7B2").Body(requestBody).Execute() + + if err != nil { + t.Fatalf("%v", err) + } + + if response.StatusCode != test.ResponseStatus { + t.Fatalf("OpenFga%v().Execute() = %v, want %v", test.Name, response.StatusCode, test.ResponseStatus) + } + + responseJson, err := got.MarshalJSON() + if err != nil { + t.Fatalf("%v", err) + } + + if *got.Allowed != *expectedResponse.Allowed { + t.Fatalf("OpenFga%v().Execute() = %v, want %v", test.Name, string(responseJson), test.JsonResponse) + } + }) + t.Run("Check with 500 error", func(t *testing.T) { test := TestDefinition{ Name: "Check", diff --git a/client/client.go b/client/client.go index 7252b73..ce3b260 100644 --- a/client/client.go +++ b/client/client.go @@ -20,11 +20,12 @@ import ( _nethttp "net/http" "time" + "golang.org/x/sync/errgroup" + fgaSdk "github.com/openfga/go-sdk" "github.com/openfga/go-sdk/credentials" internalutils "github.com/openfga/go-sdk/internal/utils" "github.com/openfga/go-sdk/telemetry" - "golang.org/x/sync/errgroup" ) var ( diff --git a/configuration.go b/configuration.go index df573b9..c0fd0db 100644 --- a/configuration.go +++ b/configuration.go @@ -16,6 +16,7 @@ import ( "net/http" "github.com/openfga/go-sdk/credentials" + "github.com/openfga/go-sdk/internal/utils/retryutils" "github.com/openfga/go-sdk/telemetry" ) @@ -25,11 +26,8 @@ const ( defaultUserAgent = "openfga-sdk go/0.6.5" ) -// RetryParams configures configuration for retry in case of HTTP too many request -type RetryParams struct { - MaxRetry int `json:"maxRetry,omitempty"` - MinWaitInMs int `json:"minWaitInMs,omitempty"` -} +// RetryParams provides configuration for retries in case of server errors +type RetryParams = retryutils.RetryParams // Configuration stores the configuration of the API client type Configuration struct { @@ -49,14 +47,6 @@ type Configuration struct { Telemetry *telemetry.Configuration `json:"telemetry,omitempty"` } -// DefaultRetryParams returns the default retry parameters -func DefaultRetryParams() *RetryParams { - return &RetryParams{ - MaxRetry: 3, - MinWaitInMs: 100, - } -} - func GetSdkUserAgent() string { return defaultUserAgent } @@ -98,15 +88,24 @@ func NewConfiguration(config Configuration) (*Configuration, error) { cfg.Telemetry = telemetry.DefaultTelemetryConfiguration() } - err := cfg.ValidateConfig() - + retryParams, err := retryutils.NewRetryParams(cfg.RetryParams) if err != nil { return nil, err } + cfg.RetryParams = retryParams + + if err := cfg.ValidateConfig(); err != nil { + return nil, err + } return cfg, nil } +// GetRetryParams +func (c *Configuration) GetRetryParams() RetryParams { + return retryutils.GetRetryParamsOrDefault(c.RetryParams) +} + // AddDefaultHeader adds a new HTTP header to the default header in the request func (c *Configuration) AddDefaultHeader(key string, value string) { c.DefaultHeaders[key] = value @@ -128,8 +127,8 @@ func (c *Configuration) ValidateConfig() error { } } - if c.RetryParams != nil && c.RetryParams.MaxRetry > 15 { - return reportError("Configuration.RetryParams.MaxRetry exceeds maximum allowed limit of 15") + if err := c.RetryParams.Validate(); err != nil { + return err } return nil diff --git a/credentials/credentials.go b/credentials/credentials.go index 94fc896..bab348a 100644 --- a/credentials/credentials.go +++ b/credentials/credentials.go @@ -7,6 +7,7 @@ import ( "net/url" "strings" + "github.com/openfga/go-sdk/internal/utils/retryutils" "github.com/openfga/go-sdk/oauth2/clientcredentials" ) @@ -99,7 +100,7 @@ func (c *Credentials) GetApiTokenHeader() *HeaderParams { // GetHttpClientAndHeaderOverrides // The main export the client uses to get a configuration with the necessary // httpClient and header overrides based on the chosen credential method -func (c *Credentials) GetHttpClientAndHeaderOverrides() (*http.Client, []*HeaderParams) { +func (c *Credentials) GetHttpClientAndHeaderOverrides(retryParams retryutils.RetryParams) (*http.Client, []*HeaderParams) { var headers []*HeaderParams var client = http.DefaultClient switch c.Method { @@ -108,6 +109,7 @@ func (c *Credentials) GetHttpClientAndHeaderOverrides() (*http.Client, []*Header ClientID: c.Config.ClientCredentialsClientId, ClientSecret: c.Config.ClientCredentialsClientSecret, TokenURL: c.Config.ClientCredentialsApiTokenIssuer, + RetryParams: retryParams, } if c.Config.ClientCredentialsApiAudience != "" { ccConfig.EndpointParams = map[string][]string{ diff --git a/example/opentelemetry/go.sum b/example/opentelemetry/go.sum deleted file mode 100644 index c0b2da5..0000000 --- a/example/opentelemetry/go.sum +++ /dev/null @@ -1,59 +0,0 @@ -github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= -github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= -github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= -github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= -github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI= -github.com/jarcoal/httpmock v1.3.1 h1:iUx3whfZWVf3jT01hQTO/Eo5sAYtB2/rqaUuOtpInww= -github.com/jarcoal/httpmock v1.3.1/go.mod h1:3yb8rc4BI7TCBhFY8ng0gjuLKJNquuDNiPaZjnENuYg= -github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= -github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= -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/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= -go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= -go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ= -go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.35.0 h1:QcFwRrZLc82r8wODjvyCbP7Ifp3UANaBSmhDSFjnqSc= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.35.0/go.mod h1:CXIWhUomyWBG/oY2/r/kLp6K/cmx9e/7DLpBuuGdLCA= -go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M= -go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE= -go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY= -go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg= -go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o= -go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w= -go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs= -go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc= -go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4= -go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4= -golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c= -golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= -golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= -golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= -golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= -golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= -golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= -google.golang.org/genproto/googleapis/api v0.0.0-20250311190419-81fb87f6b8bf h1:BdIVRm+fyDUn8lrZLPSlBCfM/YKDwUBYgDoLv9+DYo0= -google.golang.org/genproto/googleapis/api v0.0.0-20250311190419-81fb87f6b8bf/go.mod h1:jbe3Bkdp+Dh2IrslsFCklNhweNTBgSYanP1UXhJDhKg= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250311190419-81fb87f6b8bf h1:dHDlF3CWxQkefK9IJx+O8ldY0gLygvrlYRBNbPqDWuY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250311190419-81fb87f6b8bf/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I= -google.golang.org/grpc v1.71.0 h1:kF77BGdPTQ4/JZWMlb9VpJ5pa25aqvVqogsxNHHdeBg= -google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= -google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= -google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/utils/randomtime.go b/internal/utils/randomtime.go deleted file mode 100644 index 0815a90..0000000 --- a/internal/utils/randomtime.go +++ /dev/null @@ -1,25 +0,0 @@ -/** - * Go SDK for OpenFGA - * - * API version: 1.x - * Website: https://openfga.dev - * Documentation: https://openfga.dev/docs - * Support: https://openfga.dev/community - * License: [Apache-2.0](https://github.com/openfga/go-sdk/blob/main/LICENSE) - * - * NOTE: This file was auto generated by OpenAPI Generator (https://openapi-generator.tech). DO NOT EDIT. - */ - -package internalutils - -import ( - _math "math" - _rand "math/rand" -) - -// RandomTime provides a randomized time -func RandomTime(loopCount int, minWaitInMs int) int { - min := int(_math.Pow(2, float64(loopCount))) * minWaitInMs - max := int(_math.Pow(2, float64(loopCount+1))) * minWaitInMs - return _rand.Intn(max-min+1) + min -} diff --git a/internal/utils/retryutils/retryparams.go b/internal/utils/retryutils/retryparams.go new file mode 100644 index 0000000..5f8b68a --- /dev/null +++ b/internal/utils/retryutils/retryparams.go @@ -0,0 +1,59 @@ +/** + * Go SDK for OpenFGA + * + * API version: 1.x + * Website: https://openfga.dev + * Documentation: https://openfga.dev/docs + * Support: https://openfga.dev/community + * License: [Apache-2.0](https://github.com/openfga/go-sdk/blob/main/LICENSE) + * + * NOTE: This file was auto generated by OpenAPI Generator (https://openapi-generator.tech). DO NOT EDIT. + */ + +package retryutils + +import "fmt" + +// RetryParams configures configuration for retry in case of HTTP too many request +type RetryParams struct { + MaxRetry int `json:"maxRetry,omitempty"` + MinWaitInMs int `json:"minWaitInMs,omitempty"` +} + +var defaultRetryParams = RetryParams{ + MaxRetry: defaultMaxRetry, + MinWaitInMs: defaultMinWaitInMs, +} + +func (r *RetryParams) Validate() error { + if r.MaxRetry < 0 || r.MaxRetry > retryMaxAllowedNumber { + return fmt.Errorf("maxRetry must be between 0 and %d", retryMaxAllowedNumber) + + } + + if r.MinWaitInMs <= 0 { + return fmt.Errorf("maxRetry must be greater than 0") + } + + return nil +} + +func GetRetryParamsOrDefault(r *RetryParams) RetryParams { + if r == nil { + return defaultRetryParams + } + + return *r +} + +func NewRetryParams(retryParams *RetryParams) (*RetryParams, error) { + if retryParams == nil { + return &defaultRetryParams, nil + } + + if err := retryParams.Validate(); err != nil { + return &defaultRetryParams, err + } + + return retryParams, nil +} diff --git a/internal/utils/retryutils/retryparams_test.go b/internal/utils/retryutils/retryparams_test.go new file mode 100644 index 0000000..5358825 --- /dev/null +++ b/internal/utils/retryutils/retryparams_test.go @@ -0,0 +1,89 @@ +package retryutils + +import "testing" + +func TestValidateMaxRetry(t *testing.T) { + t.Run("MaxRetry within valid range", func(t *testing.T) { + params := RetryParams{MaxRetry: 2, MinWaitInMs: 100} + err := params.Validate() + if err != nil { + t.Fatalf("Expected no error, got %v", err) + } + }) + + t.Run("MaxRetry below valid range", func(t *testing.T) { + params := RetryParams{MaxRetry: -1, MinWaitInMs: 100} + err := params.Validate() + if err == nil { + t.Fatalf("Expected error, got nil") + } + }) + + t.Run("MaxRetry above valid range", func(t *testing.T) { + params := RetryParams{MaxRetry: 15 + 1, MinWaitInMs: 100} + err := params.Validate() + if err == nil { + t.Fatalf("Expected error, got nil") + } + }) +} + +func TestValidateMinWaitInMs(t *testing.T) { + t.Run("MinWaitInMs greater than 0", func(t *testing.T) { + params := RetryParams{MaxRetry: 2, MinWaitInMs: 100} + err := params.Validate() + if err != nil { + t.Fatalf("Expected no error, got %v", err) + } + }) + + t.Run("MinWaitInMs equal to 0", func(t *testing.T) { + params := RetryParams{MaxRetry: 2, MinWaitInMs: 0} + err := params.Validate() + if err == nil { + t.Fatalf("Expected error, got nil") + } + }) + + t.Run("MinWaitInMs less than 0", func(t *testing.T) { + params := RetryParams{MaxRetry: 2, MinWaitInMs: -1} + err := params.Validate() + if err == nil { + t.Fatalf("Expected error, got nil") + } + }) +} + +func TestNewRetryParamsValidation(t *testing.T) { + t.Run("Nil input returns default", func(t *testing.T) { + got, err := NewRetryParams(nil) + if err != nil { + t.Fatalf("Expected no error, got %v", err) + } + if *got != defaultRetryParams { + t.Fatalf("Expected %v, got %v", defaultRetryParams, got) + } + }) + + t.Run("Valid input returns input", func(t *testing.T) { + params := &RetryParams{MaxRetry: 2, MinWaitInMs: 100} + got, err := NewRetryParams(params) + if err != nil { + t.Fatalf("Expected no error, got %v", err) + } + if *got != *params { + t.Fatalf("Expected %v, got %v", params, got) + } + }) + + t.Run("Invalid input returns default with error", func(t *testing.T) { + params := &RetryParams{MaxRetry: -1, MinWaitInMs: 100} + got, err := NewRetryParams(params) + if err == nil { + t.Fatalf("Expected error, got nil") + } + if *got != defaultRetryParams { + t.Fatalf("Expected %v, got %v", defaultRetryParams, got) + } + }) +} diff --git a/internal/utils/retryutils/retryutils.go b/internal/utils/retryutils/retryutils.go new file mode 100644 index 0000000..fc99721 --- /dev/null +++ b/internal/utils/retryutils/retryutils.go @@ -0,0 +1,117 @@ +/** + * Go SDK for OpenFGA + * + * API version: 1.x + * Website: https://openfga.dev + * Documentation: https://openfga.dev/docs + * Support: https://openfga.dev/community + * License: [Apache-2.0](https://github.com/openfga/go-sdk/blob/main/LICENSE) + * + * NOTE: This file was auto generated by OpenAPI Generator (https://openapi-generator.tech). DO NOT EDIT. + */ + +package retryutils + +import ( + _math "math" + _rand "math/rand" + "net/http" + "strconv" + "time" +) + +const ( + RetryAfterHeaderName = "Retry-After" + RateLimitResetHeaderName = "X-RateLimit-Reset" + RateLimitResetAltHeaderName = "X-Rate-Limit-Reset" + + RetryHeaderMaxAllowableDurationInSec = 1800 + MaxBackoffTimeInSec = 120 + + retryMaxAllowedNumber = 15 + defaultMaxRetry = 3 + defaultMinWaitInMs = 100 +) + +// randomTime provides a randomized time +func randomTime(loopCount int, minWaitInMs int) time.Duration { + if minWaitInMs <= 0 { + // This is protected against in the defaults, but we should still check in case parameters are passed without the NewRetryParams function + minWaitInMs = defaultMinWaitInMs + } + + minTimeToWait := int(_math.Pow(2, float64(loopCount))) * minWaitInMs + maxTimeToWait := int(_math.Pow(2, float64(loopCount+1))) * minWaitInMs + return time.Duration(_rand.Intn(maxTimeToWait-minTimeToWait+1)+minTimeToWait) * time.Millisecond +} + +// parseRetryAfterHeadersValue parses the Retry-After header value to time.Duration +func parseRetryAfterHeaderValue(headers http.Header, headerName string) time.Duration { + retryAfter := headers.Get(headerName) + if retryAfter == "" { + return 0 + } + + // Try to parse as an integer (seconds) + if seconds, err := strconv.Atoi(retryAfter); err == nil { + return time.Duration(seconds) * time.Second + } + + // Try to parse as a date + if date, err := http.ParseTime(retryAfter); err == nil { + return time.Until(date) + } + + return 0 +} + +// parseRetryHeaderValue parses several possible retry after header value to time.Duration +// starts with Retry-After, then X-RateLimit-Reset, then X-Rate-Limit-Reset +func parseRetryHeaderValue(headers http.Header) time.Duration { + // if retryAfter is greater than 0 and less than the max backoff time, return retryAfter + timeToWait := parseRetryAfterHeaderValue(headers, RetryAfterHeaderName) + if timeToWait > 0 && timeToWait < RetryHeaderMaxAllowableDurationInSec*time.Second { + return timeToWait + } + + // if X-Rate-Limit-Reset is greater than 0 and less than the max backoff time, return retryAfter + timeToWait = parseRetryAfterHeaderValue(headers, RateLimitResetHeaderName) + if timeToWait > 0 && timeToWait < RetryHeaderMaxAllowableDurationInSec*time.Second { + return timeToWait + } + + // if X-RateLimit-Reset is greater than 0 and less than the max backoff time, return retryAfter + timeToWait = parseRetryAfterHeaderValue(headers, RateLimitResetAltHeaderName) + if timeToWait > 0 && timeToWait < RetryHeaderMaxAllowableDurationInSec*time.Second { + return timeToWait + } + + return 0 +} + +// GetTimeToWait returns the time to wait for the next retry +// returns 0 if no retry should be attempted +// loopCount: the current loop count +// maxRetry: the maximum number of retries +// minWaitInMs: the minimum wait time in milliseconds +// headers: the headers from the response +// operationName: the operation name, currently unused +func GetTimeToWait(loopCount, maxRetry, minWaitInMs int, headers http.Header, _ string) time.Duration { + // if the loop count is greater than the max retry, return 0 + if loopCount >= maxRetry { + return 0 + } + + timeToWait := parseRetryHeaderValue(headers) + // if timeToWait is greater than 0 that means it's valid and we can use it + if timeToWait > 0 { + return timeToWait + } + + timeToWait = randomTime(loopCount, minWaitInMs) + if timeToWait > 0 && timeToWait < time.Duration(MaxBackoffTimeInSec)*time.Second { + return timeToWait + } + + return time.Duration(MaxBackoffTimeInSec) * time.Second +} diff --git a/internal/utils/retryutils/retryutils_test.go b/internal/utils/retryutils/retryutils_test.go new file mode 100644 index 0000000..ad52eda --- /dev/null +++ b/internal/utils/retryutils/retryutils_test.go @@ -0,0 +1,107 @@ +package retryutils + +import ( + "net/http" + "testing" + "time" +) + +func TestParseRetryAfterHeaderValue(t *testing.T) { + t.Run("Valid integer seconds", func(t *testing.T) { + headers := http.Header{} + headers.Set(RetryAfterHeaderName, "120") + duration := parseRetryAfterHeaderValue(headers, RetryAfterHeaderName) + if duration != 120*time.Second { + t.Fatalf("Expected 120 seconds, got %v", duration) + } + }) + + t.Run("Valid date format", func(t *testing.T) { + headers := http.Header{} + futureTime := time.Now().Add(2 * time.Hour).UTC().Format(http.TimeFormat) + headers.Set(RetryAfterHeaderName, futureTime) + duration := parseRetryAfterHeaderValue(headers, RetryAfterHeaderName) + if duration <= 0 { + t.Fatalf("Expected positive 2h duration, got %v", duration) + } + }) + + t.Run("Invalid header value", func(t *testing.T) { + headers := http.Header{} + headers.Set(RetryAfterHeaderName, "invalid") + duration := parseRetryAfterHeaderValue(headers, RetryAfterHeaderName) + if duration != 0 { + t.Fatalf("Expected 0 duration, got %v", duration) + } + }) + + t.Run("Empty header value", func(t *testing.T) { + headers := http.Header{} + duration := parseRetryAfterHeaderValue(headers, RetryAfterHeaderName) + if duration != 0 { + t.Fatalf("Expected 0 duration, got %v", duration) + } + }) +} + +func TestParseRetryHeaderValue(t *testing.T) { + t.Run("Retry-After header present", func(t *testing.T) { + headers := http.Header{} + headers.Set(RetryAfterHeaderName, "120") + duration := parseRetryHeaderValue(headers) + if duration != 120*time.Second { + t.Fatalf("Expected 120 seconds, got %v", duration) + } + }) + + t.Run("X-RateLimit-Reset header present", func(t *testing.T) { + headers := http.Header{} + headers.Set(RateLimitResetHeaderName, "120") + duration := parseRetryHeaderValue(headers) + if duration != 120*time.Second { + t.Fatalf("Expected 120 seconds, got %v", duration) + } + }) + + t.Run("X-Rate-Limit-Reset header present", func(t *testing.T) { + headers := http.Header{} + headers.Set(RateLimitResetAltHeaderName, "120") + duration := parseRetryHeaderValue(headers) + if duration != 120*time.Second { + t.Fatalf("Expected 120 seconds, got %v", duration) + } + }) + + t.Run("No retry headers present", func(t *testing.T) { + headers := http.Header{} + duration := parseRetryHeaderValue(headers) + if duration != 0 { + t.Fatalf("Expected 0 duration, got %v", duration) + } + }) +} + +func TestGetTimeToWait(t *testing.T) { + t.Run("Exceed max retry count", func(t *testing.T) { + duration := GetTimeToWait(5, 3, 100, http.Header{}, "") + if duration != 0 { + t.Fatalf("Expected 0 duration, got %v", duration) + } + }) + + t.Run("Retry-After header present", func(t *testing.T) { + headers := http.Header{} + headers.Set(RetryAfterHeaderName, "120") + duration := GetTimeToWait(1, 3, 100, headers, "") + if duration != 120*time.Second { + t.Fatalf("Expected 120 seconds, got %v", duration) + } + }) + + t.Run("Random time within max backoff", func(t *testing.T) { + duration := GetTimeToWait(1, 3, 100, http.Header{}, "Check") + if duration <= 0 || duration > time.Duration(MaxBackoffTimeInSec)*time.Second { + t.Fatalf("Expected duration between 0 and %v, got %v", time.Duration(MaxBackoffTimeInSec)*time.Second, duration) + } + }) +} diff --git a/oauth2/clientcredentials/clientcredentials.go b/oauth2/clientcredentials/clientcredentials.go index be87191..f87108f 100644 --- a/oauth2/clientcredentials/clientcredentials.go +++ b/oauth2/clientcredentials/clientcredentials.go @@ -20,6 +20,7 @@ import ( "net/url" "strings" + "github.com/openfga/go-sdk/internal/utils/retryutils" "github.com/openfga/go-sdk/oauth2" "github.com/openfga/go-sdk/oauth2/internal" ) @@ -47,6 +48,8 @@ type Config struct { // client ID & client secret sent. The zero value means to // auto-detect. AuthStyle oauth2.AuthStyle + + RetryParams retryutils.RetryParams } // Token uses client credentials to retrieve a token. @@ -103,7 +106,8 @@ func (c *tokenSource) Token() (*oauth2.Token, error) { v[k] = p } - tk, err := internal.RetrieveToken(c.ctx, c.conf.ClientID, c.conf.ClientSecret, c.conf.TokenURL, v, internal.AuthStyle(c.conf.AuthStyle)) + retryParams := c.conf.RetryParams + tk, err := internal.RetrieveToken(c.ctx, c.conf.ClientID, c.conf.ClientSecret, c.conf.TokenURL, v, internal.AuthStyle(c.conf.AuthStyle), retryParams.MaxRetry, retryParams.MinWaitInMs) if err != nil { if rErr, ok := err.(*internal.RetrieveError); ok { return nil, (*oauth2.RetrieveError)(rErr) diff --git a/oauth2/internal/token.go b/oauth2/internal/token.go index 4782d7c..8c49b0b 100644 --- a/oauth2/internal/token.go +++ b/oauth2/internal/token.go @@ -20,13 +20,10 @@ import ( "sync" "time" - internalutils "github.com/openfga/go-sdk/internal/utils" + "github.com/openfga/go-sdk/internal/utils/retryutils" "github.com/openfga/go-sdk/telemetry" ) -const cMaxRetry = 3 -const cMinWaitInMs = 50 - // Token represents the credentials used to authorize // the requests to access protected resources on the OAuth 2.0 // provider's backend. @@ -189,7 +186,7 @@ func cloneURLValues(v url.Values) url.Values { return v2 } -func RetrieveToken(ctx context.Context, clientID, clientSecret, tokenURL string, v url.Values, authStyle AuthStyle) (*Token, error) { +func RetrieveToken(ctx context.Context, clientID, clientSecret, tokenURL string, v url.Values, authStyle AuthStyle, maxRetry, minWaitInMs int) (*Token, error) { needsAuthStyleProbe := authStyle == 0 if needsAuthStyleProbe { if style, ok := lookupAuthStyle(tokenURL); ok { @@ -203,7 +200,7 @@ func RetrieveToken(ctx context.Context, clientID, clientSecret, tokenURL string, if err != nil { return nil, err } - token, err := doTokenRoundTrip(ctx, req) + token, err := doTokenRoundTrip(ctx, req, maxRetry, minWaitInMs) if err != nil && needsAuthStyleProbe { // If we get an error, assume the server wants the // clientID & clientSecret in a different form. @@ -219,7 +216,7 @@ func RetrieveToken(ctx context.Context, clientID, clientSecret, tokenURL string, // So just try both ways. authStyle = AuthStyleInParams // the second way we'll try req, _ = newTokenRequest(tokenURL, clientID, clientSecret, v, authStyle) - token, err = doTokenRoundTrip(ctx, req) + token, err = doTokenRoundTrip(ctx, req, maxRetry, minWaitInMs) } if needsAuthStyleProbe && err == nil { setAuthStyle(tokenURL, authStyle) @@ -288,11 +285,11 @@ func singleTokenRoundTrip(ctx context.Context, req *http.Request) (*Token, error return token, nil } -func doTokenRoundTrip(ctx context.Context, req *http.Request) (*Token, error) { +func doTokenRoundTrip(ctx context.Context, req *http.Request, maxRetry, minWaitInMs int) (*Token, error) { var token *Token var err error - for i := 0; i < cMaxRetry; i++ { + for i := 0; i <= maxRetry; i++ { token, err = singleTokenRoundTrip(ctx, req) if err == nil { @@ -308,8 +305,11 @@ func doTokenRoundTrip(ctx context.Context, req *http.Request) (*Token, error) { // We do not want to retry any other error if rErr, ok := err.(*RetrieveError); ok { statusCode := rErr.Response.StatusCode - if statusCode == http.StatusTooManyRequests || (statusCode >= http.StatusInternalServerError && statusCode <= 599) { - time.Sleep(time.Duration(internalutils.RandomTime(i, cMinWaitInMs)) * time.Millisecond) + if statusCode == http.StatusTooManyRequests || (statusCode >= http.StatusInternalServerError && statusCode != http.StatusNotImplemented) { + timeToWait := retryutils.GetTimeToWait(i, maxRetry, minWaitInMs, rErr.Response.Header, "TokenExchange") + if timeToWait > 0 { + time.Sleep(timeToWait) + } continue } } diff --git a/oauth2/internal/token_test.go b/oauth2/internal/token_test.go index c840d36..44a1080 100644 --- a/oauth2/internal/token_test.go +++ b/oauth2/internal/token_test.go @@ -8,7 +8,6 @@ import ( "context" "fmt" "io" - "log" "math" "net/http" "net/http/httptest" @@ -18,6 +17,12 @@ import ( "github.com/jarcoal/httpmock" ) +const ( + testMaxRetry = 2 + testMinWaitInMs = 20 + testURL = "https://auth.fga.example" +) + func TestRetrieveToken_InParams(t *testing.T) { ResetAuthCache() const clientID = "client-id" @@ -32,7 +37,7 @@ func TestRetrieveToken_InParams(t *testing.T) { io.WriteString(w, `{"access_token": "ACCESS_TOKEN", "token_type": "bearer"}`) })) defer ts.Close() - _, err := RetrieveToken(context.Background(), clientID, "", ts.URL, url.Values{}, AuthStyleInParams) + _, err := RetrieveToken(context.Background(), clientID, "", ts.URL, url.Values{}, AuthStyleInParams, 1, testMinWaitInMs) if err != nil { t.Errorf("RetrieveToken = %v; want no error", err) } @@ -48,7 +53,7 @@ func TestRetrieveTokenWithContexts(t *testing.T) { })) defer ts.Close() - _, err := RetrieveToken(context.Background(), clientID, "", ts.URL, url.Values{}, AuthStyleUnknown) + _, err := RetrieveToken(context.Background(), clientID, "", ts.URL, url.Values{}, AuthStyleInParams, testMaxRetry, testMinWaitInMs) if err != nil { t.Errorf("RetrieveToken (with background context) = %v; want no error", err) } @@ -61,7 +66,7 @@ func TestRetrieveTokenWithContexts(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) cancel() - _, err = RetrieveToken(ctx, clientID, "", cancellingts.URL, url.Values{}, AuthStyleUnknown) + _, err = RetrieveToken(ctx, clientID, "", cancellingts.URL, url.Values{}, AuthStyleInParams, testMaxRetry, testMinWaitInMs) close(retrieved) if err == nil { t.Errorf("RetrieveToken (with cancelled context) = nil; want error") @@ -87,17 +92,45 @@ func TestRetrieveTokenWithContextsRetry(t *testing.T) { firstMock := httpmock.NewStringResponder(429, "") secondMock, _ := httpmock.NewJsonResponder(200, expectedResponse) - const testURL = "http://testserver.com" httpmock.RegisterResponder("POST", testURL, firstMock.Then(firstMock).Then(firstMock).Then(secondMock), ) - _, err := RetrieveToken(context.Background(), clientID, "", testURL, url.Values{}, AuthStyleUnknown) + _, err := RetrieveToken(context.Background(), clientID, "", testURL, url.Values{}, AuthStyleInParams, 3, testMinWaitInMs) if err != nil { t.Errorf("RetrieveToken (with background context) = %v; want no error", err) } } +// Test the retry logic where request is successful at the end +func TestRetrieveTokenWithContextsRetryMaxExceeded(t *testing.T) { + ResetAuthCache() + const clientID = "client-id" + + type JSONResponse struct { + AccessToken string `json:"access_token"` + TokenType string `json:"token_type"` + } + expectedResponse := JSONResponse{ + AccessToken: "ACCESS_TOKEN", + TokenType: "bearer", + } + + httpmock.Activate() + defer httpmock.DeactivateAndReset() + firstMock := httpmock.NewStringResponder(429, "") + secondMock, _ := httpmock.NewJsonResponder(200, expectedResponse) + + httpmock.RegisterResponder("POST", testURL, + firstMock.Then(firstMock).Then(firstMock).Then(secondMock), + ) + + _, err := RetrieveToken(context.Background(), clientID, "", testURL, url.Values{}, AuthStyleInParams, 2, testMinWaitInMs) + if err == nil { + t.Errorf("RetrieveToken (with background context); expected error after exceeding max retries, got none") + } +} + func TestRetrieveTokenWithContextsFailure(t *testing.T) { ResetAuthCache() const clientID = "client-id" @@ -111,12 +144,11 @@ func TestRetrieveTokenWithContextsFailure(t *testing.T) { defer httpmock.DeactivateAndReset() firstMock := httpmock.NewStringResponder(429, "") - const testURL = "http://testserver.com" httpmock.RegisterResponder("POST", testURL, firstMock, ) - _, err := RetrieveToken(context.Background(), clientID, "", testURL, url.Values{}, AuthStyleUnknown) + _, err := RetrieveToken(context.Background(), clientID, "", testURL, url.Values{}, AuthStyleInParams, testMaxRetry, testMinWaitInMs) if err == nil { t.Errorf("Expect error to be returned when oauth server fails consistently") } @@ -131,21 +163,18 @@ func TestRetrieveTokenWithUnauthorizedErrors(t *testing.T) { defer httpmock.DeactivateAndReset() firstMock := httpmock.NewStringResponder(401, "") - const testURL = "http://testserver.com" httpmock.RegisterResponder("POST", testURL, firstMock, ) - // Set AuthStyleInHeader to avoid making a discovery request - _, err := RetrieveToken(context.Background(), clientID, "", testURL, url.Values{}, AuthStyleInHeader) + // Set AuthStyleInParams to avoid making a discovery request + _, err := RetrieveToken(context.Background(), clientID, "", testURL, url.Values{}, AuthStyleInParams, testMaxRetry, testMinWaitInMs) if err == nil { t.Errorf("Expect error to be returned when oauth server fails consistently") } - log.Print(httpmock.GetTotalCallCount()) - if httpmock.GetTotalCallCount() != 1 { - t.Errorf("Expected request to not be retried on a 401") + t.Errorf("Expected request to be called once and not be retried on a 401, it was called %v times", httpmock.GetTotalCallCount()) } } @@ -168,12 +197,12 @@ func TestRetrieveTokenWithServerErrorRetries(t *testing.T) { firstMock := httpmock.NewStringResponder(500, "") secondMock, _ := httpmock.NewJsonResponder(200, expectedResponse) - const testURL = "http://testserver.com" httpmock.RegisterResponder("POST", testURL, - firstMock.Then(firstMock).Then(firstMock).Then(secondMock), + firstMock.Then(firstMock).Then(secondMock), ) - _, err := RetrieveToken(context.Background(), clientID, "", testURL, url.Values{}, AuthStyleUnknown) + // Set AuthStyleInParams to avoid making a discovery request + _, err := RetrieveToken(context.Background(), clientID, "", testURL, url.Values{}, AuthStyleInParams, testMaxRetry, testMinWaitInMs) if err != nil { t.Errorf("RetrieveToken (with background context) = %v; want no error", err) } @@ -188,21 +217,19 @@ func TestRetrieveTokenWithServerErrorEventuallyErrors(t *testing.T) { defer httpmock.DeactivateAndReset() firstMock := httpmock.NewStringResponder(500, "") - const testURL = "http://testserver.com" httpmock.RegisterResponder("POST", testURL, firstMock, ) - // Set AuthStyleInHeader to avoid making a discovery request - _, err := RetrieveToken(context.Background(), clientID, "", testURL, url.Values{}, AuthStyleInHeader) + // Set AuthStyleInParams to avoid making a discovery request + _, err := RetrieveToken(context.Background(), clientID, "", testURL, url.Values{}, AuthStyleInParams, testMaxRetry, testMinWaitInMs) if err == nil { t.Errorf("Expect error to be returned when oauth server fails consistently") } - log.Print(httpmock.GetTotalCallCount()) - - if httpmock.GetTotalCallCount() != cMaxRetry { - t.Errorf("Expected request to not be retried on a 401") + // Expect the request to be called once and then retried testMaxRetry times + if httpmock.GetTotalCallCount() != testMaxRetry+1 { + t.Errorf("Expected request to be retried %v times on a 500, it was retried %v", testMaxRetry, httpmock.GetTotalCallCount()-1) } } diff --git a/oauth2/oauth2.go b/oauth2/oauth2.go index 04b0997..0da63a4 100644 --- a/oauth2/oauth2.go +++ b/oauth2/oauth2.go @@ -12,11 +12,13 @@ import ( "bytes" "context" "errors" - "github.com/openfga/go-sdk/oauth2/internal" "net/http" "net/url" "strings" "sync" + + "github.com/openfga/go-sdk/internal/utils/retryutils" + "github.com/openfga/go-sdk/oauth2/internal" ) // NoContext is the default context you should supply if not using @@ -56,6 +58,8 @@ type Config struct { // Scope specifies optional requested permissions. Scopes []string + + RetryParams *retryutils.RetryParams } // A TokenSource is anything that can return a token. diff --git a/oauth2/token.go b/oauth2/token.go index 1c980c4..8e6d562 100644 --- a/oauth2/token.go +++ b/oauth2/token.go @@ -7,12 +7,14 @@ package oauth2 import ( "context" "fmt" - "github.com/openfga/go-sdk/oauth2/internal" "net/http" "net/url" "strconv" "strings" "time" + + "github.com/openfga/go-sdk/internal/utils/retryutils" + "github.com/openfga/go-sdk/oauth2/internal" ) // expiryDelta determines how earlier a token should be considered @@ -153,7 +155,12 @@ func tokenFromInternal(t *internal.Token) *Token { // This token is then mapped from *internal.Token into an *oauth2.Token which is returned along // with an error.. func retrieveToken(ctx context.Context, c *Config, v url.Values) (*Token, error) { - tk, err := internal.RetrieveToken(ctx, c.ClientID, c.ClientSecret, c.Endpoint.TokenURL, v, internal.AuthStyle(c.Endpoint.AuthStyle)) + retryParams, err := retryutils.NewRetryParams(c.RetryParams) + if err != nil { + return nil, err + } + + tk, err := internal.RetrieveToken(ctx, c.ClientID, c.ClientSecret, c.Endpoint.TokenURL, v, internal.AuthStyle(c.Endpoint.AuthStyle), retryParams.MaxRetry, retryParams.MinWaitInMs) if err != nil { if rErr, ok := err.(*internal.RetrieveError); ok { return nil, (*RetrieveError)(rErr)