From 76b07db96405e2fe5eaa1c398c72f8f3b9ac3490 Mon Sep 17 00:00:00 2001 From: vladp Date: Sat, 21 Feb 2026 23:45:54 +0700 Subject: [PATCH] dev add retry --- .../service/search/SearchImageService.java | 100 ++++++++++++++---- 1 file changed, 82 insertions(+), 18 deletions(-) diff --git a/src/main/java/ru/soune/nocopy/service/search/SearchImageService.java b/src/main/java/ru/soune/nocopy/service/search/SearchImageService.java index a7dfb3b..d38b935 100644 --- a/src/main/java/ru/soune/nocopy/service/search/SearchImageService.java +++ b/src/main/java/ru/soune/nocopy/service/search/SearchImageService.java @@ -32,10 +32,10 @@ public class SearchImageService { public SearchImageService() { this.httpClient = new OkHttpClient.Builder() - .connectTimeout(30, TimeUnit.SECONDS) - .writeTimeout(30, TimeUnit.SECONDS) - .readTimeout(30, TimeUnit.SECONDS) - .callTimeout(30, TimeUnit.SECONDS) + .connectTimeout(18, TimeUnit.SECONDS) + .writeTimeout(18, TimeUnit.SECONDS) + .readTimeout(18, TimeUnit.SECONDS) + .callTimeout(18, TimeUnit.SECONDS) .retryOnConnectionFailure(true) .build(); @@ -96,7 +96,6 @@ public class SearchImageService { } private String callReverseImageApiByUrl(String imageUrl, String engine, String searchType) throws IOException { - if (searchApiKey == null || searchApiKey.isBlank()) { throw new IllegalStateException("SearchAPI key not configured"); } @@ -115,26 +114,91 @@ public class SearchImageService { .header("User-Agent", "Mozilla/5.0") .build(); - long start = System.currentTimeMillis(); + int maxAttempts = 3; + IOException lastException = null; - try (Response response = httpClient.newCall(request).execute()) { + for (int attempt = 1; attempt <= maxAttempts; attempt++) { + long start = System.currentTimeMillis(); - long duration = System.currentTimeMillis() - start; - log.info("Yandex response code={}, duration={}ms", response.code(), duration); + try (Response response = httpClient.newCall(request).execute()) { + long duration = System.currentTimeMillis() - start; + log.info("Yandex response code={}, duration={}ms, attempt={}", + response.code(), duration, attempt); - if (!response.isSuccessful()) { - throw new IOException("API error: " + response.code()); + if (!response.isSuccessful()) { + throw new IOException("API error: " + response.code()); + } + + ResponseBody body = response.body(); + if (body == null) { + throw new IOException("Empty response body"); + } + + return body.string(); + + } catch (IOException e) { + lastException = e; + log.warn("Attempt {} failed for image: {}, error: {}", + attempt, imageUrl, e.getMessage()); + + if (attempt == maxAttempts) { + log.error("All {} attempts failed for image: {}", maxAttempts, imageUrl); + throw lastException; + } + + try { + Thread.sleep(500L * attempt); // 500ms, 1000ms, 1500ms + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + throw new IOException("Retry interrupted", ie); + } } - - ResponseBody body = response.body(); - if (body == null) { - throw new IOException("Empty response body"); - } - - return body.string(); } + + throw lastException; } + +// private String callReverseImageApiByUrl(String imageUrl, String engine, String searchType) throws IOException { +// +// if (searchApiKey == null || searchApiKey.isBlank()) { +// throw new IllegalStateException("SearchAPI key not configured"); +// } +// +// HttpUrl url = HttpUrl.parse("https://searchapi.io/api/v1/search") +// .newBuilder() +// .addQueryParameter("engine", engine) +// .addQueryParameter("api_key", searchApiKey) +// .addQueryParameter("url", imageUrl) +// .addQueryParameter("search_type", searchType) +// .build(); +// +// Request request = new Request.Builder() +// .url(url) +// .header("Accept", "application/json") +// .header("User-Agent", "Mozilla/5.0") +// .build(); +// +// long start = System.currentTimeMillis(); +// +// try (Response response = httpClient.newCall(request).execute()) { +// +// long duration = System.currentTimeMillis() - start; +// log.info("Yandex response code={}, duration={}ms", response.code(), duration); +// +// if (!response.isSuccessful()) { +// throw new IOException("API error: " + response.code()); +// } +// +// ResponseBody body = response.body(); +// if (body == null) { +// throw new IOException("Empty response body"); +// } +// +// return body.string(); +// } +// } + public List getAllImagesWithoutPagination(String searchApiJson, String findType) throws IOException { JsonNode root = objectMapper.readTree(searchApiJson);