Skip to content

Commit 343d7eb

Browse files
Kahncodewing328
andauthored
[cpp-ue4] Improved retry system to use Unreal's FHttpRetrySystem (#9382)
* Revert "[cpp-ue4] Added the possibility to retry requests easily with AsyncRetry method on the response and SetAutoRetryCount on the request" * [cpp-ue4] Improved retry system to use Unreal's FHttpRetrySystem * [cpp-ue4] Updated style guide link * update samples Co-authored-by: William Cheng <wing328hk@gmail.com>
1 parent 32b2ea3 commit 343d7eb

13 files changed

Lines changed: 394 additions & 380 deletions

File tree

CONTRIBUTING.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ Code change should conform to the programming style guide of the respective lang
4848
- C#: https://msdn.microsoft.com/en-us/library/vstudio/ff926074.aspx
4949
- C++: https://google.github.io/styleguide/cppguide.html
5050
- C++ (Tizen): https://wiki.tizen.org/Native_Platform_Coding_Idiom_and_Style_Guide#C.2B.2B_Coding_Style
51+
- C++ (Unreal Engine 4): https://docs.unrealengine.com/en-US/ProductionPipelines/DevelopmentSetup/CodingStandard/index.html
5152
- Clojure: https://github.com/bbatsov/clojure-style-guide
5253
- Crystal: https://crystal-lang.org/reference/conventions/coding_style.html
5354
- Dart: https://www.dartlang.org/guides/language/effective-dart/style

modules/openapi-generator/src/main/resources/cpp-ue4/api-header.mustache

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,19 @@ public:
1515
{{classname}}();
1616
~{{classname}}();
1717

18+
/* Sets the URL Endpoint.
19+
* Note: several fallback endpoints can be configured in request retry policies, see Request::SetShouldRetry */
1820
void SetURL(const FString& Url);
21+
22+
/* Adds global header params to all requests */
1923
void AddHeaderParam(const FString& Key, const FString& Value);
2024
void ClearHeaderParams();
25+
26+
/* Sets the retry manager to the user-defined retry manager. User must manage the lifetime of the retry manager.
27+
* If no retry manager is specified and a request needs retries, a default retry manager will be used.
28+
* See also: Request::SetShouldRetry */
29+
void SetHttpRetryManager(FHttpRetrySystem::FManager& RetryManager);
30+
FHttpRetrySystem::FManager& GetHttpRetryManager();
2131

2232
{{#operations}}{{#operation}}class {{operationIdCamelCase}}Request;
2333
class {{operationIdCamelCase}}Response;
@@ -27,15 +37,17 @@ public:
2737
{{#operations}}{{#operation}}{{#description}}/* {{{description}}} */
2838
{{/description}}bool {{operationIdCamelCase}}(const {{operationIdCamelCase}}Request& Request, const F{{operationIdCamelCase}}Delegate& Delegate = F{{operationIdCamelCase}}Delegate()) const;
2939
{{/operation}}{{/operations}}
30-
3140
private:
32-
{{#operations}}{{#operation}}void On{{operationIdCamelCase}}Response(FHttpRequestPtr HttpRequest, FHttpResponsePtr HttpResponse, bool bSucceeded, F{{operationIdCamelCase}}Delegate Delegate, int AutoRetryCount) const;
41+
{{#operations}}{{#operation}}void On{{operationIdCamelCase}}Response(FHttpRequestPtr HttpRequest, FHttpResponsePtr HttpResponse, bool bSucceeded, F{{operationIdCamelCase}}Delegate Delegate) const;
3342
{{/operation}}{{/operations}}
43+
FHttpRequestRef CreateHttpRequest(const Request& Request) const;
3444
bool IsValid() const;
3545
void HandleResponse(FHttpResponsePtr HttpResponse, bool bSucceeded, Response& InOutResponse) const;
3646

3747
FString Url;
3848
TMap<FString,FString> AdditionalHeaderParams;
49+
mutable FHttpRetrySystem::FManager* RetryManager = nullptr;
50+
mutable TUniquePtr<HttpRetryManager> DefaultRetryManager;
3951
};
4052

4153
{{#cppNamespaceDeclarations}}

modules/openapi-generator/src/main/resources/cpp-ue4/api-source.mustache

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,40 @@ bool {{classname}}::IsValid() const
4545
return true;
4646
}
4747

48+
void {{classname}}::SetHttpRetryManager(FHttpRetrySystem::FManager& InRetryManager)
49+
{
50+
if(RetryManager != &GetHttpRetryManager())
51+
{
52+
DefaultRetryManager.Reset();
53+
RetryManager = &InRetryManager;
54+
}
55+
}
56+
57+
FHttpRetrySystem::FManager& {{classname}}::GetHttpRetryManager()
58+
{
59+
return *RetryManager;
60+
}
61+
62+
FHttpRequestRef {{classname}}::CreateHttpRequest(const Request& Request) const
63+
{
64+
if (!Request.GetRetryParams().IsSet())
65+
{
66+
return FHttpModule::Get().CreateRequest();
67+
}
68+
else
69+
{
70+
if (!RetryManager)
71+
{
72+
// Create default retry manager if none was specified
73+
DefaultRetryManager = MakeUnique<HttpRetryManager>(6, 60);
74+
RetryManager = DefaultRetryManager.Get();
75+
}
76+
77+
const HttpRetryParams& Params = Request.GetRetryParams().GetValue();
78+
return RetryManager->CreateRequest(Params.RetryLimitCountOverride, Params.RetryTimeoutRelativeSecondsOverride, Params.RetryResponseCodes, Params.RetryVerbs, Params.RetryDomains);
79+
}
80+
}
81+
4882
void {{classname}}::HandleResponse(FHttpResponsePtr HttpResponse, bool bSucceeded, Response& InOutResponse) const
4983
{
5084
InOutResponse.SetHttpResponse(HttpResponse);
@@ -96,7 +130,7 @@ bool {{classname}}::{{operationIdCamelCase}}(const {{operationIdCamelCase}}Reque
96130
if (!IsValid())
97131
return false;
98132
99-
FHttpRequestRef HttpRequest = FHttpModule::Get().CreateRequest();
133+
FHttpRequestRef HttpRequest = CreateHttpRequest(Request);
100134
HttpRequest->SetURL(*(Url + Request.ComputePath()));
101135
102136
for(const auto& It : AdditionalHeaderParams)
@@ -106,26 +140,15 @@ bool {{classname}}::{{operationIdCamelCase}}(const {{operationIdCamelCase}}Reque
106140

107141
Request.SetupHttpRequest(HttpRequest);
108142

109-
HttpRequest->OnProcessRequestComplete().BindRaw(this, &{{classname}}::On{{operationIdCamelCase}}Response, Delegate, Request.GetAutoRetryCount());
143+
HttpRequest->OnProcessRequestComplete().BindRaw(this, &{{classname}}::On{{operationIdCamelCase}}Response, Delegate);
110144
return HttpRequest->ProcessRequest();
111145
}
112146

113-
void {{classname}}::On{{operationIdCamelCase}}Response(FHttpRequestPtr HttpRequest, FHttpResponsePtr HttpResponse, bool bSucceeded, F{{operationIdCamelCase}}Delegate Delegate, int AutoRetryCount) const
147+
void {{classname}}::On{{operationIdCamelCase}}Response(FHttpRequestPtr HttpRequest, FHttpResponsePtr HttpResponse, bool bSucceeded, F{{operationIdCamelCase}}Delegate Delegate) const
114148
{
115149
{{operationIdCamelCase}}Response Response;
116-
Response.SetHttpRequest(HttpRequest);
117-
118150
HandleResponse(HttpResponse, bSucceeded, Response);
119-
120-
if(!Response.IsSuccessful() && AutoRetryCount > 0)
121-
{
122-
HttpRequest->OnProcessRequestComplete().BindRaw(this, &{{classname}}::On{{operationIdCamelCase}}Response, Delegate, AutoRetryCount - 1);
123-
Response.AsyncRetry();
124-
}
125-
else
126-
{
127-
Delegate.ExecuteIfBound(Response);
128-
}
151+
Delegate.ExecuteIfBound(Response);
129152
}
130153

131154
{{/operation}}

modules/openapi-generator/src/main/resources/cpp-ue4/model-base-header.mustache

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,40 @@
55
#include "Interfaces/IHttpResponse.h"
66
#include "Serialization/JsonWriter.h"
77
#include "Dom/JsonObject.h"
8+
#include "HttpRetrySystem.h"
9+
#include "Containers/Ticker.h"
810

911
{{#cppNamespaceDeclarations}}
1012
namespace {{this}}
1113
{
1214
{{/cppNamespaceDeclarations}}
1315

1416
typedef TSharedRef<TJsonWriter<>> JsonWriter;
17+
using namespace FHttpRetrySystem;
18+
19+
struct {{dllapi}} HttpRetryManager : public FManager, public FTickerObjectBase
20+
{
21+
using FManager::FManager;
22+
23+
bool Tick(float DeltaTime) final;
24+
};
25+
26+
struct {{dllapi}} HttpRetryParams
27+
{
28+
HttpRetryParams(
29+
const FRetryLimitCountSetting& InRetryLimitCountOverride = FRetryLimitCountSetting(),
30+
const FRetryTimeoutRelativeSecondsSetting& InRetryTimeoutRelativeSecondsOverride = FRetryTimeoutRelativeSecondsSetting(),
31+
const FRetryResponseCodes& InRetryResponseCodes = FRetryResponseCodes(),
32+
const FRetryVerbs& InRetryVerbs = FRetryVerbs(),
33+
const FRetryDomainsPtr& InRetryDomains = FRetryDomainsPtr()
34+
);
35+
36+
FRetryLimitCountSetting RetryLimitCountOverride;
37+
FRetryTimeoutRelativeSecondsSetting RetryTimeoutRelativeSecondsOverride;
38+
FRetryResponseCodes RetryResponseCodes;
39+
FRetryVerbs RetryVerbs;
40+
FRetryDomainsPtr RetryDomains;
41+
};
1542

1643
class {{dllapi}} Model
1744
{
@@ -28,11 +55,12 @@ public:
2855
virtual void SetupHttpRequest(const FHttpRequestRef& HttpRequest) const = 0;
2956
virtual FString ComputePath() const = 0;
3057

31-
void SetAutoRetryCount(int InCount) { AutoRetryCount = InCount; }
32-
int GetAutoRetryCount() const { return AutoRetryCount; }
58+
/* Enables retry and optionally sets a retry policy for this request */
59+
void SetShouldRetry(const HttpRetryParams& Params = HttpRetryParams()) { RetryParams = Params; }
60+
const TOptional<HttpRetryParams>& GetRetryParams() const { return RetryParams; }
3361

3462
private:
35-
int AutoRetryCount = 0;
63+
TOptional<HttpRetryParams> RetryParams;
3664
};
3765

3866
class {{dllapi}} Response
@@ -44,8 +72,6 @@ public:
4472
void SetSuccessful(bool InSuccessful) { Successful = InSuccessful; }
4573
bool IsSuccessful() const { return Successful; }
4674

47-
void AsyncRetry() const;
48-
4975
virtual void SetHttpResponseCode(EHttpResponseCodes::Type InHttpResponseCode);
5076
EHttpResponseCodes::Type GetHttpResponseCode() const { return ResponseCode; }
5177

@@ -55,15 +81,11 @@ public:
5581
void SetHttpResponse(const FHttpResponsePtr& InHttpResponse) { HttpResponse = InHttpResponse; }
5682
const FHttpResponsePtr& GetHttpResponse() const { return HttpResponse; }
5783

58-
void SetHttpRequest(const FHttpRequestPtr& InHttpRequest) { HttpRequest = InHttpRequest; }
59-
const FHttpRequestPtr& GetHttpRequest() const { return HttpRequest; }
60-
6184
private:
6285
bool Successful;
6386
EHttpResponseCodes::Type ResponseCode;
6487
FString ResponseString;
6588
FHttpResponsePtr HttpResponse;
66-
FHttpRequestPtr HttpRequest;
6789
};
6890

6991
{{#cppNamespaceDeclarations}}
Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,30 @@
11
{{>licenseInfo}}
22
#include "{{modelNamePrefix}}BaseModel.h"
33

4-
#include "Async/Async.h"
5-
64
{{#cppNamespaceDeclarations}}
75
namespace {{this}}
86
{
97
{{/cppNamespaceDeclarations}}
108

9+
bool HttpRetryManager::Tick(float DeltaTime)
10+
{
11+
FManager::Update();
12+
return true;
13+
}
14+
15+
HttpRetryParams::HttpRetryParams(const FRetryLimitCountSetting& InRetryLimitCountOverride /*= FRetryLimitCountSetting()*/,
16+
const FRetryTimeoutRelativeSecondsSetting& InRetryTimeoutRelativeSecondsOverride /*= FRetryTimeoutRelativeSecondsSetting()*/,
17+
const FRetryResponseCodes& InRetryResponseCodes /*= FRetryResponseCodes()*/,
18+
const FRetryVerbs& InRetryVerbs /*= FRetryVerbs()*/,
19+
const FRetryDomainsPtr& InRetryDomains /*= FRetryDomainsPtr() */)
20+
: RetryLimitCountOverride(InRetryLimitCountOverride)
21+
, RetryTimeoutRelativeSecondsOverride(InRetryTimeoutRelativeSecondsOverride)
22+
, RetryResponseCodes(InRetryResponseCodes)
23+
, RetryVerbs(InRetryVerbs)
24+
, RetryDomains(InRetryDomains)
25+
{
26+
}
27+
1128
void Response::SetHttpResponseCode(EHttpResponseCodes::Type InHttpResponseCode)
1229
{
1330
ResponseCode = InHttpResponseCode;
@@ -18,15 +35,6 @@ void Response::SetHttpResponseCode(EHttpResponseCodes::Type InHttpResponseCode)
1835
}
1936
}
2037

21-
void Response::AsyncRetry() const
22-
{
23-
// Unfortunately, it is currently usafe to call ProcessRequest() directly here.
24-
// This is because the HttpManager will remove all references to this HttpRequest in FHttpManager::Tick including the new request we just added, instead of removing just one.
25-
// This will lead to the request's destruction and eventually a crash.
26-
// The only solution is therefore to ensure we are taking an extra reference to the request, and that the request is added after the queue is flushed.
27-
Async(EAsyncExecution::TaskGraph, [AddRef = FHttpRequestPtr(GetHttpRequest())](){ AddRef->ProcessRequest(); });
28-
}
29-
3038
{{#cppNamespaceDeclarations}}
3139
}
3240
{{/cppNamespaceDeclarations}}

samples/client/petstore/cpp-ue4/Private/OpenAPIBaseModel.cpp

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,28 @@
1212

1313
#include "OpenAPIBaseModel.h"
1414

15-
#include "Async/Async.h"
16-
1715
namespace OpenAPI
1816
{
1917

18+
bool HttpRetryManager::Tick(float DeltaTime)
19+
{
20+
FManager::Update();
21+
return true;
22+
}
23+
24+
HttpRetryParams::HttpRetryParams(const FRetryLimitCountSetting& InRetryLimitCountOverride /*= FRetryLimitCountSetting()*/,
25+
const FRetryTimeoutRelativeSecondsSetting& InRetryTimeoutRelativeSecondsOverride /*= FRetryTimeoutRelativeSecondsSetting()*/,
26+
const FRetryResponseCodes& InRetryResponseCodes /*= FRetryResponseCodes()*/,
27+
const FRetryVerbs& InRetryVerbs /*= FRetryVerbs()*/,
28+
const FRetryDomainsPtr& InRetryDomains /*= FRetryDomainsPtr() */)
29+
: RetryLimitCountOverride(InRetryLimitCountOverride)
30+
, RetryTimeoutRelativeSecondsOverride(InRetryTimeoutRelativeSecondsOverride)
31+
, RetryResponseCodes(InRetryResponseCodes)
32+
, RetryVerbs(InRetryVerbs)
33+
, RetryDomains(InRetryDomains)
34+
{
35+
}
36+
2037
void Response::SetHttpResponseCode(EHttpResponseCodes::Type InHttpResponseCode)
2138
{
2239
ResponseCode = InHttpResponseCode;
@@ -27,13 +44,4 @@ void Response::SetHttpResponseCode(EHttpResponseCodes::Type InHttpResponseCode)
2744
}
2845
}
2946

30-
void Response::AsyncRetry() const
31-
{
32-
// Unfortunately, it is currently usafe to call ProcessRequest() directly here.
33-
// This is because the HttpManager will remove all references to this HttpRequest in FHttpManager::Tick including the new request we just added, instead of removing just one.
34-
// This will lead to the request's destruction and eventually a crash.
35-
// The only solution is therefore to ensure we are taking an extra reference to the request, and that the request is added after the queue is flushed.
36-
Async(EAsyncExecution::TaskGraph, [AddRef = FHttpRequestPtr(GetHttpRequest())](){ AddRef->ProcessRequest(); });
37-
}
38-
3947
}

0 commit comments

Comments
 (0)