Skip to content

Commit df585be

Browse files
committed
fix: add retry policy for OAUTH2 abstract client
1 parent 5a1c8f7 commit df585be

2 files changed

Lines changed: 90 additions & 85 deletions

File tree

app/Services/Apis/AbstractOAuth2Api.php

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
<?php namespace App\Services\Apis;
2-
32
/**
43
* Copyright 2020 OpenStack Foundation
54
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -12,18 +11,21 @@
1211
* See the License for the specific language governing permissions and
1312
* limitations under the License.
1413
**/
15-
use App\Services\Auth\OAuth2ClientFactory;
16-
use GuzzleHttp\Exception\ClientException;
14+
use App\Services\Auth\OAuth2ClientFactory;;
1715
use Illuminate\Support\Facades\Config;
1816
use libs\utils\ICacheService;
1917
use Illuminate\Support\Facades\Log;
2018
use League\OAuth2\Client\Provider\GenericProvider;
19+
use GuzzleHttp\Exception\RequestException;
20+
use GuzzleHttp\Exception\ClientException;
2121
/**
2222
* Class AbstractOAuth2Api
2323
* @package App\Services\Apis
2424
*/
2525
abstract class AbstractOAuth2Api
2626
{
27+
const MaxRetries = 3;
28+
2729
/**
2830
* @var ICacheService
2931
*/
@@ -74,6 +76,51 @@ private function getAccessTokenCacheKey():string{
7476
}
7577

7678
/**
79+
* @param \Closure $callback
80+
* @return mixed|null
81+
* @throws \Exception
82+
*/
83+
protected function invokeWithRetry(\Closure $callback)
84+
{
85+
$retry = 0;
86+
$done = false;
87+
$result = null;
88+
89+
while (!$done and $retry < self::MaxRetries) {
90+
try {
91+
$result = $callback($this);
92+
$done = true;
93+
} catch (ClientException $ex) {
94+
Log::warning("AbstractOAuth2Api::invokeWithRetry retrying ...");
95+
$retry++;
96+
if ($retry === self::MaxRetries) {
97+
if ($ex->getCode() == 404) {
98+
return null;
99+
}
100+
throw $ex;
101+
}
102+
$this->cleanAccessToken();
103+
Log::warning($ex);
104+
}
105+
catch (RequestException $ex){
106+
$this->cleanAccessToken();
107+
Log::error($ex);
108+
if($ex->getCode() == 404){
109+
return null;
110+
}
111+
throw $ex;
112+
}
113+
catch (\Exception $ex) {
114+
$this->cleanAccessToken();
115+
Log::error($ex);
116+
throw $ex;
117+
}
118+
}
119+
return $result;
120+
}
121+
122+
123+
/**
77124
* @return string|null
78125
* @throws \League\OAuth2\Client\Provider\Exception\IdentityProviderException
79126
*/
@@ -109,6 +156,7 @@ protected function getAccessToken():?string{
109156
throw $ex;
110157
}
111158
}
159+
Log::debug(sprintf("AbstractOAuth2Api::getAccessToken - returning access token %s", $token));
112160
return $token;
113161
}
114162

app/Services/Apis/ExternalUserApi.php

Lines changed: 39 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
* See the License for the specific language governing permissions and
1212
* limitations under the License.
1313
**/
14-
use GuzzleHttp\Exception\RequestException;
14+
1515
use models\exceptions\ValidationException;
1616
use libs\utils\ICacheService;
1717
use GuzzleHttp\Client;
@@ -21,6 +21,7 @@
2121
use Illuminate\Support\Facades\Config;
2222
use Illuminate\Support\Facades\Log;
2323
use Exception;
24+
2425
/**
2526
* Class ExternalUserApi
2627
* @package App\Services
@@ -50,11 +51,11 @@ public function __construct(ICacheService $cacheService)
5051
$stack->push(GuzzleRetryMiddleware::factory());
5152

5253
$this->client = new Client([
53-
'handler' => $stack,
54-
'base_uri' => Config::get('idp.base_url') ?? '',
55-
'timeout' => Config::get('curl.timeout', 60),
54+
'handler' => $stack,
55+
'base_uri' => Config::get('idp.base_url') ?? '',
56+
'timeout' => Config::get('curl.timeout', 60),
5657
'allow_redirects' => Config::get('curl.allow_redirects', false),
57-
'verify' => Config::get('curl.verify_ssl_cert', true),
58+
'verify' => Config::get('curl.verify_ssl_cert', true),
5859
]);
5960
}
6061

@@ -65,8 +66,9 @@ public function __construct(ICacheService $cacheService)
6566
*/
6667
public function getUserByEmail(string $email)
6768
{
68-
try {
69-
Log::debug(sprintf("ExternalUserApi::getUserByEmail email %s", $email));
69+
Log::debug(sprintf("ExternalUserApi::getUserByEmail email %s", $email));
70+
71+
return $this->invokeWithRetry(function () use ($email) {
7072

7173
$query = [
7274
'access_token' => $this->getAccessToken()
@@ -88,20 +90,7 @@ public function getUserByEmail(string $email)
8890
$data = json_decode($response->getBody()->getContents(), true);
8991

9092
return intval($data['total']) > 0 ? $data['data'][0] : null;
91-
}
92-
catch (RequestException $ex){
93-
$this->cleanAccessToken();
94-
Log::warning($ex);
95-
if($ex->getCode() == 404){
96-
return null;
97-
}
98-
throw $ex;
99-
}
100-
catch (Exception $ex) {
101-
$this->cleanAccessToken();
102-
Log::error($ex);
103-
throw $ex;
104-
}
93+
});
10594
}
10695

10796
/**
@@ -116,32 +105,28 @@ public function registerUser(string $email, ?string $first_name, ?string $last_n
116105
{
117106
Log::debug(sprintf("ExternalUserApi::registerUser email %s first_name %s last_name %s", $email, $first_name, $last_name));
118107

119-
try {
108+
return $this->invokeWithRetry(function () use ($email, $first_name, $last_name, $company) {
109+
120110
$query = [
121111
'access_token' => $this->getAccessToken()
122112
];
123113

124-
if(empty($email))
114+
if (empty($email))
125115
throw new ValidationException("Email field es required.");
126116

127117
$response = $this->client->post('/api/v1/user-registration-requests', [
128118
'query' => $query,
129119
RequestOptions::JSON => [
130-
'email' => $email,
120+
'email' => $email,
131121
'first_name' => $first_name,
132-
'last_name' => $last_name,
133-
'company' => $company
122+
'last_name' => $last_name,
123+
'company' => $company
134124
]
135125
]
136126
);
137127

138128
return json_decode($response->getBody()->getContents(), true);
139-
}
140-
catch (Exception $ex) {
141-
$this->cleanAccessToken();
142-
Log::error($ex);
143-
throw $ex;
144-
}
129+
});
145130
}
146131

147132
const AppName = 'REGISTRATION_SERVICE';
@@ -173,8 +158,10 @@ public function getAppConfig(): array
173158
*/
174159
public function getUserById(int $id)
175160
{
176-
try {
177-
Log::debug(sprintf("ExternalUserApi::getUserById id %s", $id));
161+
162+
Log::debug(sprintf("ExternalUserApi::getUserById id %s", $id));
163+
164+
return $this->invokeWithRetry(function () use ($id) {
178165

179166
$query = [
180167
'access_token' => $this->getAccessToken()
@@ -185,25 +172,12 @@ public function getUserById(int $id)
185172
]
186173
);
187174

188-
$res = json_decode($response->getBody()->getContents(), true);
175+
$res = json_decode($response->getBody()->getContents(), true);
189176

190177
Log::debug(sprintf("ExternalUserApi::getUserById id %s res %s", $id, json_encode($res)));
191178

192179
return $res;
193-
}
194-
catch (RequestException $ex){
195-
$this->cleanAccessToken();
196-
Log::warning($ex);
197-
if($ex->getCode() == 404){
198-
return null;
199-
}
200-
throw $ex;
201-
}
202-
catch (Exception $ex) {
203-
$this->cleanAccessToken();
204-
Log::error($ex);
205-
throw $ex;
206-
}
180+
});
207181
}
208182

209183
/**
@@ -227,7 +201,8 @@ public function updateUser(int $id, ?string $first_name, ?string $last_name, ?st
227201
)
228202
);
229203

230-
try {
204+
return $this->invokeWithRetry(function () use ($id, $first_name, $last_name, $company_name) {
205+
231206
$query = [
232207
'access_token' => $this->getAccessToken()
233208
];
@@ -236,26 +211,16 @@ public function updateUser(int $id, ?string $first_name, ?string $last_name, ?st
236211
'query' => $query,
237212
RequestOptions::JSON => [
238213
'first_name' => $first_name,
239-
'last_name' => $last_name,
240-
'company' => $company_name
214+
'last_name' => $last_name,
215+
'company' => $company_name
241216
]
242217
]
243218
);
244219

245220
$res = json_decode($response->getBody()->getContents(), true);
246221
Log::debug(sprintf("ExternalUserApi::updateUser id %s res %s", $id, json_encode($res)));
247222
return $res;
248-
}
249-
catch(RequestException $ex){
250-
$this->cleanAccessToken();
251-
Log::warning($ex);
252-
return null;
253-
}
254-
catch (Exception $ex) {
255-
$this->cleanAccessToken();
256-
Log::error($ex);
257-
throw $ex;
258-
}
223+
});
259224
}
260225

261226
/**
@@ -268,8 +233,10 @@ public function updateUser(int $id, ?string $first_name, ?string $last_name, ?st
268233
*/
269234
public function getUserRegistrationRequest(string $email)
270235
{
271-
try {
272-
Log::debug(sprintf("ExternalUserApi::getUserRegistrationRequest email %s", $email));
236+
237+
Log::debug(sprintf("ExternalUserApi::getUserRegistrationRequest email %s", $email));
238+
239+
return $this->invokeWithRetry(function () use ($email) {
273240

274241
$query = [
275242
'access_token' => $this->getAccessToken(),
@@ -288,12 +255,7 @@ public function getUserRegistrationRequest(string $email)
288255
]);
289256

290257
return json_decode($response->getBody()->getContents(), true);
291-
}
292-
catch (Exception $ex) {
293-
$this->cleanAccessToken();
294-
Log::error($ex);
295-
throw $ex;
296-
}
258+
});
297259
}
298260

299261
/**
@@ -310,28 +272,23 @@ public function updateUserRegistrationRequest(
310272
{
311273
Log::debug(sprintf("ExternalUserApi::updateUserRegistrationRequest id %s", $id));
312274

313-
try {
275+
return $this->invokeWithRetry(function () use ($id, $first_name, $last_name, $company_name, $country) {
314276
$query = [
315277
'access_token' => $this->getAccessToken()
316278
];
317279

318280
$response = $this->client->put(sprintf('/api/v1/user-registration-requests/%s', $id), [
319281
'query' => $query,
320282
RequestOptions::JSON => [
321-
'first_name' => $first_name,
322-
'last_name' => $last_name,
323-
'company' => $company_name,
324-
'country' => $country
283+
'first_name' => $first_name,
284+
'last_name' => $last_name,
285+
'company' => $company_name,
286+
'country' => $country
325287
]
326288
]
327289
);
328290
return json_decode($response->getBody()->getContents(), true);
329-
}
330-
catch (Exception $ex) {
331-
$this->cleanAccessToken();
332-
Log::error($ex);
333-
throw $ex;
334-
}
291+
});
335292
}
336293
}
337294

0 commit comments

Comments
 (0)