Skip to content

Commit 91bdb3c

Browse files
fix: add retry logic for Mittwald getDatabase and getDatabaseUser API calls
1 parent 9531595 commit 91bdb3c

1 file changed

Lines changed: 53 additions & 22 deletions

File tree

src/Database/Manager/MittwaldApi.php

Lines changed: 53 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,11 @@ public function create(): void
9494
throw new \RuntimeException('Database is not ready for feature ' . $this->getFeatureName() . ' after waiting period.');
9595
}
9696

97-
$database = $this->getDatabase($responseBody->getId());
97+
$database = $this->getDatabase(
98+
$responseBody->getId(),
99+
(int) get('mittwald_database_wait', 30),
100+
(int) get('mittwald_database_retries', 20),
101+
);
98102

99103
$reachable = $this->checkDatabaseHostReachable(
100104
$database->getHostName(),
@@ -114,7 +118,11 @@ public function create(): void
114118
// dependency for db_sync_tool, TYPO3 CLI, and all subsequent remote commands.
115119
$databaseHost = $this->resolveHostnameToIp($database->getHostName());
116120

117-
$user = $this->getDatabaseUser($responseBody->getUserId());
121+
$user = $this->getDatabaseUser(
122+
$responseBody->getUserId(),
123+
(int) get('mittwald_database_wait', 30),
124+
(int) get('mittwald_database_retries', 20),
125+
);
118126

119127
$this->initDatabaseConfiguration($database, $user, $databaseHost);
120128
}
@@ -204,35 +212,58 @@ private function getDatabaseByFeature(string $feature): ?MySqlDatabase
204212
* @throws GuzzleException
205213
* @throws UnexpectedResponseException
206214
*/
207-
private function getDatabase(string $id): MySqlDatabase
215+
private function getDatabase(string $id, int $waitingTime = 10, int $maxRetries = 5): MySqlDatabase
208216
{
209-
$response = $this->initClient()
210-
->database()
211-
->getMysqlDatabase(
212-
new GetMysqlDatabaseRequest(
213-
mysqlDatabaseId: $id
214-
)
215-
);
216-
217-
218-
return $response->getBody();
217+
return $this->retryOnUnexpectedResponse(
218+
fn () => $this->initClient()
219+
->database()
220+
->getMysqlDatabase(new GetMysqlDatabaseRequest(mysqlDatabaseId: $id))
221+
->getBody(),
222+
'getDatabase',
223+
$waitingTime,
224+
$maxRetries,
225+
);
219226
}
220227

221228
/**
222229
* @throws GuzzleException
223230
* @throws UnexpectedResponseException
224231
*/
225-
private function getDatabaseUser(string $id): MysqlUser
232+
private function getDatabaseUser(string $id, int $waitingTime = 10, int $maxRetries = 5): MysqlUser
226233
{
227-
$response = $this->initClient()
228-
->database()
229-
->getMysqlUser(
230-
new GetMysqlUserRequest(
231-
mysqlUserId: $id
232-
)
233-
);
234+
return $this->retryOnUnexpectedResponse(
235+
fn () => $this->initClient()
236+
->database()
237+
->getMysqlUser(new GetMysqlUserRequest(mysqlUserId: $id))
238+
->getBody(),
239+
'getDatabaseUser',
240+
$waitingTime,
241+
$maxRetries,
242+
);
243+
}
244+
245+
/**
246+
* @template T
247+
* @param callable(): T $operation
248+
* @return T
249+
* @throws UnexpectedResponseException
250+
*/
251+
private function retryOnUnexpectedResponse(callable $operation, string $label, int $waitingTime, int $maxRetries): mixed
252+
{
253+
while ($maxRetries > 0) {
254+
try {
255+
return $operation();
256+
} catch (UnexpectedResponseException $e) {
257+
$maxRetries--;
258+
debug("{$label}: {$e->getMessage()}, remaining attempts: {$maxRetries}");
259+
if ($maxRetries <= 0) {
260+
throw $e;
261+
}
262+
sleep($waitingTime);
263+
}
264+
}
234265

235-
return $response->getBody();
266+
throw new \RuntimeException("{$label} failed after all retry attempts.");
236267
}
237268

238269
private function initDatabaseConfiguration(MySqlDatabase $database, MySqlUser $user, string $databaseHost): void

0 commit comments

Comments
 (0)