From a382f7005a23f557b25b03cc11d8e33669a85214 Mon Sep 17 00:00:00 2001 From: bko Date: Fri, 19 Apr 2024 13:47:28 +0200 Subject: [PATCH] Retries resolving image if any exception occurred In some cases, the image we want to resolve is not yet available. It is therefore important to try again after a short waiting time. This is the case, for example, when we request a variant of an image that has not yet been created. Fixes: SIRI-958 --- .../pdf/AsyncLoadedImageElement.java | 48 ++++++++++++++----- 1 file changed, 37 insertions(+), 11 deletions(-) diff --git a/src/main/java/sirius/web/templates/pdf/AsyncLoadedImageElement.java b/src/main/java/sirius/web/templates/pdf/AsyncLoadedImageElement.java index 087f4f42e..5d443d111 100644 --- a/src/main/java/sirius/web/templates/pdf/AsyncLoadedImageElement.java +++ b/src/main/java/sirius/web/templates/pdf/AsyncLoadedImageElement.java @@ -16,6 +16,7 @@ import org.xhtmlrenderer.render.RenderingContext; import sirius.kernel.async.CallContext; import sirius.kernel.commons.Tuple; +import sirius.kernel.commons.Wait; import sirius.kernel.health.Exceptions; import sirius.web.security.ScopeInfo; import sirius.web.security.UserContext; @@ -39,6 +40,7 @@ */ public final class AsyncLoadedImageElement implements ITextReplacedElement { + private static final int MAX_ATTEMPTS = 3; private final Thread resolvingThread; private final int cssWidth; private final int cssHeight; @@ -62,20 +64,44 @@ public AsyncLoadedImageElement(PdfReplaceHandler handler, String uri, int cssWid ScopeInfo scopeInfo = UserContext.getCurrentScope(); resolvingThread = Thread.startVirtualThread(() -> { UserContext.get().setCurrentScope(scopeInfo); - try { - semaphore.acquire(); - image = handler.resolveUri(uri, null, cssWidth, cssHeight); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - Exceptions.handle(e); - } catch (Exception e) { - Exceptions.handle(e); - } finally { - semaphore.release(); - } + startResolvingResource(uri, handler, semaphore, 1); }); } + private void startResolvingResource(String uri, PdfReplaceHandler handler, Semaphore semaphore, int attempt) { + Exception exception = null; + try { + semaphore.acquire(); + image = handler.resolveUri(uri, null, cssWidth, cssHeight); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + exception = e; + } catch (Exception e) { + exception = e; + } finally { + semaphore.release(); + if (image == null || exception != null) { + retryOrFail(uri, handler, semaphore, attempt, exception); + } + } + } + + private void retryOrFail(String uri, PdfReplaceHandler handler, Semaphore semaphore, int attempt, Exception exception) { + if (exception instanceof InterruptedException) { + // we should accept that the thread is interrupted and don't try again + Exceptions.handle(exception); + return; + } + if (attempt < MAX_ATTEMPTS) { + Wait.millis(500); + startResolvingResource(uri, handler, semaphore, attempt + 1); + } else if (exception != null) { + Exceptions.handle(exception); + } else { + Exceptions.handle().withSystemErrorMessage("Could not resolve image: %s", uri).handle(); + } + } + /** * Returns the resolved image. *