Skip to content

Commit 407150a

Browse files
authored
fix: retries for uploads (#806)
1 parent 5d00302 commit 407150a

File tree

4 files changed

+57
-21
lines changed

4 files changed

+57
-21
lines changed

src/main/java/com/crowdin/cli/client/CrowdinClientCore.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,6 @@ protected static <T> List<T> executeRequestFullList(BiFunction<Integer, Integer,
7777
return directories;
7878
}
7979

80-
protected static <T> T executeRequestWithPossibleRetry(Map<BiPredicate<String, String>, ResponseException> errorHandlers, Supplier<T> request) throws ResponseException {
81-
return executeRequestWithPossibleRetries(errorHandlers, request, 2, defaultMillisToRetry);
82-
}
83-
8480
protected static <T> T executeRequestWithPossibleRetries(Map<BiPredicate<String, String>, ResponseException> errorHandlers, Supplier<T> request, int maxAttempts, long millisToRetry) throws ResponseException {
8581
if (maxAttempts < 1) {
8682
throw new MaxNumberOfRetriesException();
@@ -93,6 +89,7 @@ protected static <T> T executeRequestWithPossibleRetries(Map<BiPredicate<String,
9389
} catch (InterruptedException ie) {
9490
// ignore
9591
}
92+
System.out.printf("Attempting to retry the request due to the error: %s%n", e.getMessage());
9693
return executeRequestWithPossibleRetries(errorHandlers, request, maxAttempts - 1, millisToRetry);
9794
}
9895
}

src/main/java/com/crowdin/cli/client/CrowdinProjectClient.java

Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.crowdin.cli.client;
22

3+
import com.crowdin.cli.utils.Utils;
34
import com.crowdin.client.branches.model.*;
45
import com.crowdin.client.core.model.PatchRequest;
56
import com.crowdin.client.labels.model.AddLabelRequest;
@@ -212,10 +213,16 @@ public Long uploadStorage(String fileName, InputStream content) throws Response
212213
Map<BiPredicate<String, String>, ResponseException> errorHandlers = new LinkedHashMap<BiPredicate<String, String>, ResponseException>() {{
213214
put((code, message) -> StringUtils.containsAny(message, "streamIsEmpty", "Stream size is null. Not empty content expected"),
214215
new EmptyFileException("Not empty content expected"));
216+
put((code, message) -> Utils.isServerErrorCode(code), new RepeatException("Server Error"));
217+
put((code, message) -> message.contains("Request aborted"), new RepeatException("Request aborted"));
218+
put((code, message) -> message.contains("Connection reset"), new RepeatException("Connection reset"));
215219
}};
216-
Storage storage = executeRequest(errorHandlers, () -> this.client.getStorageApi()
217-
.addStorage(fileName, content)
218-
.getData());
220+
Storage storage = executeRequestWithPossibleRetries(
221+
errorHandlers,
222+
() -> this.client.getStorageApi().addStorage(fileName, content).getData(),
223+
3,
224+
2 * 1000
225+
);
219226
return storage.getId();
220227
}
221228

@@ -244,28 +251,38 @@ public void deleteDirectory(Long directoryId) {
244251
@Override
245252
public void updateSource(Long sourceId, UpdateFileRequest request) throws ResponseException {
246253
Map<BiPredicate<String, String>, ResponseException> errorHandlers = new LinkedHashMap<BiPredicate<String, String>, ResponseException>() {{
247-
put((code, message) -> message.contains("File from storage with id #" + request.getStorageId() + " was not found"), new RepeatException());
254+
put((code, message) -> message.contains("File from storage with id #" + request.getStorageId() + " was not found"), new RepeatException("File not found in the storage"));
255+
put((code, message) -> Utils.isServerErrorCode(code), new RepeatException("Server Error"));
256+
put((code, message) -> message.contains("Request aborted"), new RepeatException("Request aborted"));
257+
put((code, message) -> message.contains("Connection reset"), new RepeatException("Connection reset"));
248258
put((code, message) -> StringUtils.contains(message, "Invalid SRX specified"), new ResponseException("Invalid SRX file specified"));
249259
put((code, message) -> code.equals("409"), new FileInUpdateException());
250260
}};
251-
executeRequestWithPossibleRetry(
261+
executeRequestWithPossibleRetries(
252262
errorHandlers,
253-
() -> this.client.getSourceFilesApi()
254-
.updateOrRestoreFile(this.projectId, sourceId, request));
263+
() -> this.client.getSourceFilesApi().updateOrRestoreFile(this.projectId, sourceId, request),
264+
3,
265+
2 * 1000
266+
);
255267
}
256268

257269
@Override
258270
public FileInfo addSource(AddFileRequest request) throws ResponseException {
259271
Map<BiPredicate<String, String>, ResponseException> errorHandlers = new LinkedHashMap<BiPredicate<String, String>, ResponseException>() {{
260-
put((code, message) -> message.contains("File from storage with id #" + request.getStorageId() + " was not found"), new RepeatException());
272+
put((code, message) -> message.contains("File from storage with id #" + request.getStorageId() + " was not found"), new RepeatException("File not found in the storage"));
273+
put((code, message) -> Utils.isServerErrorCode(code), new RepeatException("Server Error"));
274+
put((code, message) -> message.contains("Request aborted"), new RepeatException("Request aborted"));
275+
put((code, message) -> message.contains("Connection reset"), new RepeatException("Connection reset"));
261276
put((code, message) -> StringUtils.contains(message, "Name must be unique"), new ExistsResponseException());
262277
put((code, message) -> StringUtils.contains(message, "Invalid SRX specified"), new ResponseException("Invalid SRX file specified"));
263278
put((code, message) -> StringUtils.containsAny(message, "isEmpty", "Value is required and can't be empty"), new EmptyFileException("Value is required and can't be empty"));
264279
}};
265-
return executeRequestWithPossibleRetry(
280+
return executeRequestWithPossibleRetries(
266281
errorHandlers,
267-
() -> this.client.getSourceFilesApi()
268-
.addFile(this.projectId, request).getData());
282+
() -> this.client.getSourceFilesApi().addFile(this.projectId, request).getData(),
283+
3,
284+
2 * 1000
285+
);
269286
}
270287

271288
@Override
@@ -303,12 +320,17 @@ public void uploadTranslations(String languageId, UploadTranslationsRequest requ
303320
put((code, message) -> code.equals("0") && message.equals("File is not allowed for language"),
304321
new WrongLanguageException());
305322
put((code, message) -> message.contains("File from storage with id #" + request.getStorageId() + " was not found"),
306-
new RepeatException());
323+
new RepeatException("File not found in the storage"));
324+
put((code, message) -> Utils.isServerErrorCode(code), new RepeatException("Server Error"));
325+
put((code, message) -> message.contains("Request aborted"), new RepeatException("Request aborted"));
326+
put((code, message) -> message.contains("Connection reset"), new RepeatException("Connection reset"));
307327
}};
308-
executeRequestWithPossibleRetry(
328+
executeRequestWithPossibleRetries(
309329
errorhandlers,
310-
() -> this.client.getTranslationsApi()
311-
.uploadTranslations(this.projectId, languageId, request));
330+
() -> this.client.getTranslationsApi().uploadTranslations(this.projectId, languageId, request),
331+
3,
332+
2 * 1000
333+
);
312334
}
313335

314336
@Override
@@ -321,13 +343,16 @@ public void uploadTranslationStringsBased(String languageId, UploadTranslationsS
321343
public ProjectBuild startBuildingTranslation(BuildProjectTranslationRequest request) throws ResponseException {
322344
Map<BiPredicate<String, String>, ResponseException> errorHandler = new LinkedHashMap<BiPredicate<String, String>, ResponseException>() {{
323345
put((code, message) -> code.equals("409") && message.contains("Another build is currently in progress"),
324-
new RepeatException());
346+
new RepeatException("Another build is currently in progress"));
347+
put((code, message) -> Utils.isServerErrorCode(code), new RepeatException("Server Error"));
348+
put((code, message) -> message.contains("Request aborted"), new RepeatException("Request aborted"));
349+
put((code, message) -> message.contains("Connection reset"), new RepeatException("Connection reset"));
325350
}};
326351
return executeRequestWithPossibleRetries(
327352
errorHandler,
328353
() -> this.client.getTranslationsApi().buildProjectTranslation(this.projectId, request).getData(),
329354
3,
330-
60 * 100
355+
6 * 1000
331356
);
332357
}
333358

src/main/java/com/crowdin/cli/client/RepeatException.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,8 @@ class RepeatException extends ResponseException {
55
public RepeatException() {
66
super();
77
}
8+
9+
public RepeatException(String message) {
10+
super(message);
11+
}
812
}

src/main/java/com/crowdin/cli/utils/Utils.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,4 +182,14 @@ public static String encodeURL(@NonNull String toEncode) {
182182
public static String toSingleLineString(String str) {
183183
return str.replaceAll("[\r\n]+", " ");
184184
}
185+
186+
public static boolean isServerErrorCode(String code) {
187+
int statusCode;
188+
try {
189+
statusCode = Integer.parseInt(code);
190+
} catch (NumberFormatException e) {
191+
return false;
192+
}
193+
return statusCode >= 500 && statusCode < 600;
194+
}
185195
}

0 commit comments

Comments
 (0)